2
votes

I have a web page that does a lot of calculations as part of it's loading.

I want to display a spinner bar while the page is "thinking" so that the end user knows the delay is to be expected.

The way I was going to do this is to display a GIF file that would be a spinning wheel, and hide the table that would be my output.

The problem is, once the function starts, updates to the page seem to freeze until the function is done. Therefore, the end user never sees the "In Process" section.

The sample code I put together to demonstrate my problem is:

<!DOCTYPE html>
<html>
<body>

<script>
function show(id, value) {
    document.getElementById(id).style.display = value ? 'block' : 'none';
}
function Processing(x)
{
    if (x === true)
    {
        show('page', false);
        show('loading', true);
    }
    else
    {
        show('page', true);
        show('loading', false);
    }
}

function MainProcess()
{
    Processing(true)  // Set to "Show processing..."

    var start = new Date().getTime();  // Sleep a few seconds
    for (var i = 0; i < 5; i++) {
        if ((new Date().getTime() - start) < 3000) { i = 1 }
    }
    Processing(false) // Set to "Show Completed processing..."
}

window.onload = function() {
  show('page', false);
  show('loading', false);
};
</script>

<div id="loading">
    <h1>Processing your request.</h1>
</div>

<div id="page">
    <DIV class="body">
        <h3>Done Processing your request.</h3>
    </DIV>
</div>
<div id="buttons">
    <button onclick="MainProcess();">Start Timer</button>
    <button onclick="Processing(false);">Set to Completed</button>
    <button onclick="Processing(true);">Set to Processing</button>
</body>
</html>

When I run this, it presents three buttons.

When you hit "Start Timer", it should show processing for a few seconds, then display done. Instead, the button changes colors and otherwise appears to do nothing till the timer is done, and it displays complete.

(I am new to JavaScript but a seasoned pro in several other languages. Is there a "DoEvents" type of call I can make like in Visual Basic or Powershell?)

2

2 Answers

2
votes

The problem seems to be that the DOM update (i.e. changing the display properties on your DIVs) doesn't complete before your processing function starts. One option would be to use window.setTimeout to delay the start of your processing function to allow the DOM update to complete:

function MainProcess()
{
    Processing(true);  // Set to "Show processing..."

    // Pause for 100 ms before starting time-consuming code to allow dom update to c
    var domUpdateDelay = 100;
    window.setTimeout(function() {

                        var start = new Date().getTime();  // Sleep a few seconds
                        for (var i = 0; i < 5; i++) {
                            if ((new Date().getTime() - start) < 3000) { i = 1 }
                        }

                        Processing(false) // Set to "Show Completed processing..."
                      }, 100);
}

window.setTimeout takes two arguments: the first argument is a function that runs after x milliseconds, where x is the second argument.

The problem with this approach is that an appropriate delay for setTimeout will vary across machines/users/browsers/runs. However, my guess is that this will probably not be an issue in 99% of cases.

0
votes

I think you can take advantage of a function like setTimeout (https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout), say:

setTimeout(function() {
  Processing(false);
}, 5000);

I think what's happening is you're nearly crashing the browser with that loop. I may have misunderstood what parts of your question were just there for demonstration purposes.