JavaScript Performance – Incremental Asynchronous Processing

I have an application where the hierarchical data is displayed as a table and I need to provide the ability to expand and collapse the nodes (I explained how this can be done in my Nested TBODYs post). With large data sets this had a lot of problem and Netscape displays the standard dialog about stop/continue the script. After a bit of research, it turned out that using the setTimeout method, the long running code can be made asynchronous.

So, I thought that’s not a big deal. Just call the function in setTimeout. After doing that, I still had the same problem. Then, it appears that even with setTimeout, the code shouldn’t be running for too long or otherwise I would end up with the same stop/continue dialog.

Then it turns out, the solution is to keep calling the setTimeout multiple times and each time doing only a small part of the computation. Now, how the heck can this be done when you have a big loop? Below are the steps to do that.

Say you had code like


for(var i=0;i<rows.length;i++) {
... // some logic
}

Change this to


var i=0;
function dosomething() {
var count = 0;
for(;i<rows.length;i++) {
... // original logic
count++;
if(count == 10) // change this to an appropriate number
break;
}
if(i<rows.length)
setTimeout(dosomething,0);
}

This is pretty much it!

Now, say you want to do something at the end of such long logic in loop. How can this be done? You can do this by using a callback function. So, the above code would be changed to


var i=0;

function dosomething(callbackf) {
var count = 0;
for(;i<rows.length;i++) {
... // original logic
count++;
if(count == 10) // change this to an appropriate number
break;
}
if(i<rows.length)
setTimeout(dosomething,0);
else if(callbackf) callbackf();
}

That’s it, now at the end of this incremental asynchronous processing, you get a hook to do some additional logic. Infact, you can keep nesting these incremental-asynchronous computations each of which calling at the end of the other.

Couple of things to note:

1. The dosomething should be a function defined within the context of another function and the loop variable. This essentially creates a closure for the loop variable. Defining the function as a top level function will not work.
2. In my specific case, I had defined the dosomething function twice, once in each part of the if-else statement. For some reason, this didn’t work in IE. Giving a different name for each case worked though.
3. In the above code, where the count is incremented, if you have logic that skips doing anything for certain increments of the loop variable, i, then don’t increment the count variable. For example, in my hierarchical data expansion/collapse functionality, there are times where the rows are already hidden and I don’t have to hide them again. This improves the speed a bit more as the number of chunks of incremental processing are optimized.

Advertisements

2 Comments

Filed under DHTML, javascript

2 responses to “JavaScript Performance – Incremental Asynchronous Processing

  1. Pingback: Asynchronous Looping in JavaScript — Tumuski

  2. Phil G.

    Thanks. I know you wrote this almost 4 years ago, but it was very helpful to me as I start to learn JavaScript and jQuery and in particular dealing with asynchronous logic control.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s