views:

1800

answers:

9

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
});
A: 

May be if you try using a delay of, lets say, 5 milli seconds between each loop to let the browser do other things. Ive have not ever tryed this, but i think it can work. Also it will slow the task.

setTimeout("",5);
Gero
-1. If you pass an empty string to setTimeout it won't help solve the author's problem.
SolutionYogi
+7  A: 

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();
tj111
should even work with a timeout of 0
Christoph
I decided on this method, except I only run the setTimeout every 50 elements. And yes, it works with a timeout of 0.
Chris B
+2  A: 

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.

Gabe Moothart
+4  A: 

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.

Mikko Tapionlinna
A: 

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

olliej
A: 

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

Scott Evernden
+12  A: 

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.

Helgi
This was a great idea - use the setTimeout periodically. It works with a timeout of 0.
Chris B
I've done exactly this for several web apps that required massive data processing on the client end. Works like a charm, even if it does require a bit of restructuring.
Toji
A: 

@Chris - did you get this working? I'm looking for the same solution. I changed my each function to a for loop, but my browser still hangs for a few seconds before it starts loading.

@Toji - can you help me with this code?...a full example

@Calvin - you should only post answers here. But to answer your question - it doesn't matter so much what method you use to iterate your function. The point is that you execute a setTimeout on the function every n iterations of the function.
Chris B
A: 

Can someone tell me how to help me in english. I dont speak computerese. My browser is always freezing and I have to shut down and start all over. A large waste of my time. It happens just about every half hour. If not more often.

Santanita