jquery .each() alternative is not looping properly

六眼飞鱼酱① 提交于 2019-12-11 14:27:35

问题


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.


回答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  );
}; 


来源:https://stackoverflow.com/questions/4372932/jquery-each-alternative-is-not-looping-properly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!