asynchBatch Javascript Function

A while ago, I wrote about using setTimeout with a 0 timeout in order to asynchronously perform certain actions, so that the browser’s UI thread will be returned while your fat init function runs in the background.

However, in using this technique, I’ve run into some situations where even this is not enough. If your code is going through some very long loop, it can freeze the browser just the same by using 100% of the CPU that your operating system has allocated to the browser. As a result, asynchronous or not, it still locks up for a second. Admittedly, it’s not as bad as if the whole thing were being run synchronously, but it’s still there.

In the application programming world, if you have a thread that’s hogging resources at a certain point in your code, you can “sleep” for a moment. The sleep command says, “Let the OS do what it has to, and get back to me as soon as you can.” This frees up resources and keeps your program from locking up the machine. If you do sleep(0) at about every 10th iteration in your giant loop, it can make a world of difference in the responsiveness of your program.

This function is a way to do this in a Javascript world. asynchBatch is a function that instruments this kind of periodic release by performing a batch of operations on an array in periodic steps. Every 10 elements, it will let the OS have control for a moment, using window.setTimeout.

var asychBatch = function(items, action, done, step, pause) {
  var len=items.length;
  var index=0;
  if(!step || isNaN(step) || step < 0) {
    step=10;
  }
  if(!pause || isNaN(pause) || pause < 0) {
    pause=0;
  }
  if(!done || typeof(done) !== 'function') {
    done=function(){};
  }
  var batch=function() {
    for(var i=0; (i < step || step === 0) && index < len; i++, index++) {
      action(items[index],items,index);
    }
    if(index < len) {
      window.setTimeout(batch,pause);
    } else {
      done(items);
    }
  };
  window.setTimeout(batch,pause);
};

The first two arguments are required. items is an array of items, and action is the function that will be executed on each one. done is a function that will be executed when the loop is completed. (By default, done is just an empty function.) step allows you to tweak the step size (which is 10 by default.) Set step to 0 to do them all in one go (but that kind of defeats the purpose a bit.) pause allows you to give the OS a little more control by specifying a wait time (in milliseconds) between each chunk. If it’s really not important to get your action done quickly, then setting a pause value will make it even more unobtrusive.

action will receive each item as an argument, and done will receive the whole array as an argument.

Here’s an example of asynchBatch in action:

// before.
var links=document.getElementsByTagName('a');
for(var i=links.length-1; i>-1; i--) {
  doStuffWithLink(a); // <--- lags here, because there are 10000 links on the page!
}
doSomethingElse(links);
 
// after. Takes longer to be done, but feels smoother and doesn't lag.
asynchBatch(document.getElementsByTagName('a'), doStuffWithLink, 10, doSomethingElse);

Leave a Reply

Comments are moderated like crazy using a variety of plugins. There is a very high likelihood that your comment won't show up right away, especially if you have never commented here before, but it was not deleted.

Please be patient, and do not post your comment more than once. It will show up once it is approved.

You must be logged in to post a comment.