Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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
});
share|improve this question
Get a faster machine! – Josh Stodola Apr 3 '09 at 17:44
4  
Get a faster language! No, really: unless it's absolutely necessary, don't use JS for this - as you see, it's 1) single-threaded and 2) slow. – Piskvor Apr 3 '09 at 20:34
3  
This is a client-side function, and JS is necessary. – Chris B Apr 20 '09 at 20:04
@Chris - Seriously. Don't do this. – Triptych Aug 20 '09 at 21:25
4  
@Triptych - And his options are? Certainly one would hope that much heavy lifting like this could be performed server side, but since we don't know his situation it's best to assume that he has good reason for doing it client-side, and when working client side in a web app, you only really have a choice between Javascript and, well... Javascript. – Toji Aug 27 '09 at 18:11

8 Answers

up vote 19 down vote accepted

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.

share|improve this answer
2  
This was a great idea - use the setTimeout periodically. It works with a timeout of 0. – Chris B Apr 22 '09 at 20:38
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 Aug 27 '09 at 18:12
Cool code. Maybe I'm missing something, but I had to add a index++ and a break after the setTimeout() in order to get this to work. – D.Tate Apr 12 at 22:53

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();
share|improve this answer
should even work with a timeout of 0 – Christoph Apr 3 '09 at 22:00
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 Apr 20 '09 at 20:05
thanks so much for that code – Adam Waite May 8 '12 at 21:44

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.

share|improve this answer

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.

share|improve this answer

Long loops without freezing the browser now seem to be possible: http://turboid.net/artikel/real-loops-in-javascript.php

share|improve this answer

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

share|improve this answer

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);
share|improve this answer
-1. If you pass an empty string to setTimeout it won't help solve the author's problem. – SolutionYogi Aug 27 '09 at 18:33

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

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.