How to stop intense Javascript loop from freezing the browser

Viewed 54408

I'm using Javascript to parse an XML file with about 3,500 elements. I'm using a jQuery "each" function, but I could use any form of loop.
The problem is that the browser freezes for a few seconds while the loop executes. What's the best way to stop freezing the browser without slowing the code down too much?

$(xmlDoc).find("Object").each(function() {
    //Processing here
});
10 Answers

I would ditch the "each" function in favour of a for loop since it is faster. I would also add some waits using the "setTimeout" but only every so often and only if needed. You don't want to wait for 5ms each time because then processing 3500 records would take approx 17.5 seconds.

Below is an example using a for loop that processes 100 records (you can tweak that) at 5 ms intervals which gives a 175 ms overhead.

var xmlElements = $(xmlDoc).find('Object');
var length = xmlElements.length;
var index = 0;
var process = function() {
  for (; index < length; index++) {
    var toProcess = xmlElements[index];
    // Perform xml processing
    if (index + 1 < length && index % 100 == 0) {
        setTimeout(process, 5);
    }
  }
};
process();

I would also benchmark the different parts of the xml processing to see if there is a bottleneck somewhere that may be fixed. You can benchmark in firefox using firebug's profiler and by writing out to the console like this:

// start benchmark
var t = new Date();
// some xml processing
console.log("Time to process: " + new Date() - t + "ms");

Hope this helps.

Set a timeOut between processing to prevent the loop cycle from eating up all the browser resources. In total it would only take a few seconds to process and loop through everything, not unreasonable for 3,500 elements.

var xmlElements = $(xmlDoc).find('Object');

var processing = function() {
  var element = xmlElements.shift();

  //process element;

  if (xmlElements.length > 0) {
    setTimeout(processing, 5);
  }
}

processing();

I'd consider converting the 3500 elements from xml to JSON serverside or even better upload it to server converted, so that it's native to JS from the getgo.

This would minimize your load and prolly make the file size smaller too.

you can setTimeout() with duration of ZERO and it will yield as desired

Javascript is single-threaded, so aside from setTimeout, there's not much you can do. If using Google Gears is an option for your site, they provide the ability to run javascript in a true background thread.

You could use the HTML5 workers API, but that will only work on Firefox 3.1 and Safari 4 betas atm.

Related