jquery .each() 替代方案未正确循环

发布于 2024-10-06 12:22:11 字数 1583 浏览 5 评论 0原文

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

我有一个页面,循环遍历 URL 列表,对它们进行 Ajax 调用(使用 jquery),从返回的 HTML 中获取数据,并将其显示在桌子。这些电话工作正常。由于实时获取这些数据需要一段时间(可能最多需要 5 分钟来循环列表、返回数据、显示数据等),Chrome 和 IE 等浏览器在这个繁重的处理过程中会“锁定”——Chrome 实际上定期显示“页面无响应”消息,而 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 );
}; 

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

放我走吧 2024-10-13 12:22:11

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

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

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

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  );
}; 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文