In a place where your fantasy can roam free, there won't be any boundaries to what your imagination can create.
Misha’s Tech Playground
graphics, fun and code play
I'm crazy - but who cares? My ideas are constantly dwelling and this is the place for them to pour out and form into something good. Only active participation will ultimately make this place come to life.
Progress monitoring with JavaScript
If you ever happen do develop a web application using Javascript you might stumble upon the occasion where a process might take a fair amount of time to calculate.
The Problem
If your script needs more than a couple of seconds, most likely this fact will result in a message like this:

Okay, you might think just drop in some code to output something while your script processes an array with say... 40k Elements (200 x 200). The issue we face is that JavaScript in Browsers is single threaded.
So the output code you have in your processing loop will be stored in a queue until the processing is done. This of course looks like your browser is stalled until suddenly there is a huge amount of data on your page.
Several JavaScript applications offer an approach that is not very user friendly. Until the script is finished you'll see an animated gif of a spinning circle or a phrase like waiting... (usually with an animated ellipsis). The real solution is only slightly more complicated but gives far more feedback to the user.
Real Progress Bars (or other shapes) are something all modern desktop applications offer. Web Applications made with Flash or other Technologies offer this as well.
How to do this in JavaScript is what we look at next …
The Solution
The not so secret recipe to free the queue to do some DOM modifications (which we need to update our progress display) is using recursive functions instead of nested loops.
Common (no progress monitoring = bad for huge data) solution
This is the basic everyday loop structure that you would use to alter the elements of an array. However, due to JavaScript's nature you won't see the results of this function until the outer loop is completely finished.
-
var max = array.length*array[0].length; // number of iterations
-
var cnt = 0; // already completed iterations
-
var pBar = document.getElementById('progressbar');
-
for (var i=0; i <array.length; i++) {
-
for (var j=0; j <array[i].length; j++) {
-
// do something
-
// increase cnt and calculate new bar width
-
pBar.style.width = ++cnt / max * 100 + "%";
-
};
-
};
Advanced Solution
To get the monitoring updating in (near) realtime – depending on your loop length – we can use this recursive function:
-
function myProcess(n, i) {
-
for (var j=0; j <n; j++) {
-
array[i][j] = // do something with this here
-
};
-
document.getElementById("progressBar").style.width = ++i / n *100 + "%";
-
if (i <n) {
-
window.setTimeout(function() {myProcess(n, i)}, 0);
-
} else {
-
completeProcess();
-
}
-
}
Basically this function replaces the outer loop from the first example. Calling itself with a timeout (even if it is 0) frees the Interpreter to process the queue. When the queue is empty the next iteration begins.
Due to this behavior, there is a slight overhead. Which causes the function to be slightly slower (although not really noticeable). But the benefits are these:
- the user will be up to date on the functions progress and therefore think it is faster
- the "script takes too long" error will be prevented since the process is sliced into smaller chunks
Now you have probably noticed that the function is called with several parameters. Namely n, and i. These variables have been defined in a helper function that I use to do all the things that shouldn't be directly in the processing functions, since they would eventually cause substantial overhead due to extra if's and else's scattered around.
The variables themselves are quite self explanatory , n being how often the function should be called, and i being the current iteration.
Further there is a function called completeProcess which is executed once all iterations are finished. Here are the two functions:
initProcess()
-
function initProcess(fn, n) {
-
var pBar = document.getElementById("progressBar");
-
pBar.style.display = "block";
-
pBar.innerHTML = "working…";
-
-
// call the defined function
-
fn(n, 0);
-
}
completeProcess()
-
function completeProcess() {
-
var pBar = document.getElementById("progressBar");
-
// chnange the text to signalize we are finished
-
pBar.innerHTML = "DONE!";
-
-
// hide the progress bar after one second
-
// to be able to hand over the variable pBar,
-
// the call needs to be wrapped in an enclosure
-
window.setTimeout(function(){ pBar.style.display = "none"; }, 1000);
-
}
As you can see, this is no magic at all, just some way to trick JavaScript to show us what is going on.
To call the initProcess function you just need to pass it the name of your processing function and the number of iterations you need. That way you can reuse the init and complete functions for multiple processes as well.
I hope this helps a few people with their need for monitoring JavaScript processes.
Tags: code performance
One Response to “Progress monitoring with JavaScript”
Leave a Reply
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
Having a busy animation in Javascript...
Looking into my logs recently I noticed that lots of people come here to find out how they can add an animated ellipsis or a spinning circle animation to show that their script is busy. Although I already showed how to do Progress monitoring with JavaS...