0

Hopefully I'm just missing something and this is simple...

I have a page that loops through a list of URL's, makes Ajax calls to them (with jquery), grabs data from the HTML that is returned, and displays it in a table. These calls work fine. Since grabbing this data in real-time takes a while (possibly up to 5 minutes to loop through the list, return data, display it, etc..) browsers like Chrome and IE 'lock up' during this heavy processing -- Chrome actually periodically shows the 'Page Unresponsive' message, while IE just appears to be hanging, then all of a sudden, results show on the screen.

To solve this, I researched how to optimize the jQuery .each() function and found a custom plugin called slowEach (LINK) which basically inserts a small timeout after each loop iteration -- so that the browser gets a response, and doesn't think the client is unresponsive. I've updated my code to call the slowEach plugin instead of .each and everything works fine, ALMOST! It seems that after the first iteration -- the plugin actually executes extra code -- all the way to the end of my callback function, then suddenly wants to jump back into the loop and continue the rest of the iterations correctly.

I'm having a hard time tracing why this happens.

Here is my code (parseXml is just a callback function that processes some XML data):

function parseXml(x)
{
  var $rowArray = $(x).find("[nodeName=z:row]");

   $rowArray.slowEach(250, function(index) {  
     // ... processing each returned row
    });
// ... extra processing after the loop is completed.  Show data on the screen.
};

Here is the slowEach plugin:

$.slowEach = function( array, interval, callback ) {
        if( ! array.length ) return;
        var i = 0;
        next();
        function next() {
            if( callback.call( array[i], i, array[i] ) !== false )
                if( ++i < array.length )
                    setTimeout( next, interval );
        }
    };

    $.fn.slowEach = function( interval, callback ) {
        $.slowEach( this, interval, callback );
}; 

This code somehow gets to the 'extra processing' part of my code -- only on the first iteration through the loop. Very odd. Maybe some extra eyeballs can help me understand why the code is doing this. Let me know if more information is needed! Thanks.

erbridge
  • 1,376
  • 12
  • 27
tresstylez
  • 1,809
  • 6
  • 29
  • 41

1 Answers1

1

When .slowEach uses setTimout, it essentially defers that function's (the content of the each function) execution until all other page processing is done. Therefore the code outside of the slowEach calls will all execute, including the code after it's called. What you need to do is add another function to the .sloweach function to call after all the items are processed, and put your // ... extra processing ... code there.

Untested code, but this should work or at least get you going in the right direction:

function parseXml(x)
{
  var $rowArray = $(x).find("[nodeName=z:row]");

   $rowArray.slowEach(250, function(index) {  
        // ... processing each returned row
    }, function() {
        // ... extra processing after the loop is completed.  
        // Show data on the screen.
    });
};

Altering the plugin:

$.slowEach = function( array, interval, callback, onCompletion ) {
        if( ! array.length ) return;
        var i = 0;
        next();
        function next() {
            if( callback.call( array[i], i, array[i] ) !== false )
                if( ++i < array.length )
                    setTimeout( next, interval );
                else
                    setTimeout( onCompletion, interval );
        }
    };

    $.fn.slowEach = function( interval, callback, onCompletion  ) {
        $.slowEach( this, interval, callback, onCompletion  );
}; 
jball
  • 24,791
  • 9
  • 70
  • 92
  • Awesome! This worked PERFECTLY! Code executed on the first run. Looking into setTimeout was definitely the culprit. I'll have to read up on it a bit more. Thanks jball. – tresstylez Dec 07 '10 at 03:24
  • @tresstylez, glad to help. Here's a good resource on javascript timing: http://ejohn.org/blog/how-javascript-timers-work/ – jball Dec 07 '10 at 03:32