The only way to ensure that the animation actually occurs is for longRunningMethod
to yield to the browser periodically. It's not uncommon for the UI rendering thread to block on the JavaScript thread, so changes you make to the DOM aren't shown until the next time the JavaScript thread yields. You can yield by calling setTimeout
with a timeout of 0
(which will be longer than 0ms — obviously — on most browser implementations; many clamp that value to at least 4ms and possibly as much as 10ms).
Example: Here's a script that adds 500 divs, but gives the browser no opportunity to show the work in progress or (usually) animate anything:
jQuery(function($) {
$("#btnGo").click(function() {
var n;
display("Loading...");
for (n = 0; n < 500; ++n) {
$("<div/>").html("Div #" + n).appendTo(document.body);
}
display("Done loading");
function display(msg) {
$("<p/>").html(msg).appendTo(document.body);
}
});
});
Live example * Example with spinner graphic
As you can see, it never yields, and so when you click the button, the page freezes for a moment, and then all 500 divs and the messages appear.
Contrast with this other end of the spectrum, which yields between every div:
jQuery(function($) {
$("#btnGo").click(function() {
display("Loading...");
addDivs(0, 500, function() {
display("Done loading");
});
function addDivs(current, max, callback) {
if (current < max) {
$("<div/>").html("Div #" + current).appendTo(document.body);
setTimeout(function() {
addDivs(current + 1, max, callback);
}, 0);
}
else {
callback();
}
}
function display(msg) {
$("<p/>").html(msg).appendTo(document.body);
}
});
});
Live example * Example with spinner graphic
Since that yields, you can see the work in progress.
You might notice that the second script takes longer, possibly much longer, in real time to achieve the same result. This is because the yields take time, as does the browser updating the display. In practice, you'll want to find a balance between the first example and the second — something that yields often enough to show progress, but not so often that the process takes an unnecessarily long time to complete.