jquery .each()替代方法没有正确循环

时间:2010-12-07 02:43:49

标签: jquery loops optimization jquery-plugins each

希望我只是遗漏了一些东西,这很简单......

我有一个循环遍历URL列表的页面,对它们进行Ajax调用(使用jquery),从返回的HTML中抓取数据,并将其显示在表中。这些调用工作正常。由于实时抓取这些数据需要一段时间(可能需要长达5分钟才能遍历列表,返回数据,显示它等等。)Chrome和IE等浏览器在这个繁重的处理过程中“锁定” - 实际上是Chrome定期显示“Page Unresponsive”消息,而IE似乎只是挂起,然后突然,结果显示在屏幕上。

为了解决这个问题,我研究了如何优化jQuery .each()函数并找到了一个名为 slowEach LINK)的自定义插件,它基本上在每次循环迭代后插入一个小超时 - 以便浏览器获得响应,并且不认为客户端没有响应。我已经更新了我的代码来调用slowEach插件而不是.each,一切正常,几乎可以!似乎在第一次迭代之后 - 插件实际上执行了额外的代码 - 一直到我的回调函数的末尾,然后突然想要跳回到循环并继续正确地继续其余的迭代。

我很难跟踪为什么会发生这种情况。

这是我的代码(parseXml只是一个处理一些XML数据的回调函数):

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.
};

这是slowEach插件:

$.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 );
}; 

这段代码以某种方式进入我代码的“额外处理”部分 - 仅在循环的第一次迭代中。很奇怪。也许一些额外的眼球可以帮助我理解代码为什么这样做。如果需要更多信息,请告诉我!感谢。

1 个答案:

答案 0 :(得分:1)

.slowEach使用setTimout时,它基本上推迟了该函数(each函数的内容)执行,直到完成所有其他页面处理。因此,slowEach调用之外的代码将全部执行,包括调用后的代码。您需要做的是向.sloweach函数添加另一个函数,以便在处理完所有项目后调用,并将// ... extra processing ...代码放在那里。

未经测试的代码,但这应该有效或至少让您朝着正确的方向前进:

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.
    });
};

更改插件:

$.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  );
};