简体   繁体   English

我怎样才能推迟每个循环的jQuery

[英]How can I defer a jQuery each loop

I am doing "heavy" canvas operations in a jQuery each loop causing slower devices (IE and the iPad) to sometimes become totally unresponsive. 我在每个循环的jQuery中进行“重”画布操作,导致较慢的设备(IE和iPad)有时变得完全没有响应。

So I was thinking I could use underscore's _.defer() to queue the functions in my each loop like: 所以我想我可以使用下划线的_.defer()来排列每个循环中的函数,如:

function handleAsset = _.defer(function(){
//weightlifting goes here (partly async)
});

$.each(assets, handleAsset);

Yet this throws a weird error (the stack trace points to the $.each ): 然而,这会抛出一个奇怪的错误(堆栈跟踪指向$.each ):

Uncaught TypeError: Object 20877 has no method 'call'

Is this approach flawed? 这种做法有缺陷吗? Is this due to async operations going on inside the handler function? 这是由于处理程序函数内部的异步操作吗? Is there another / a better way to achieve this? 还有另一种/更好的方法来实现这一目标吗?

It is flawed. 它有缺陷。 You should try to decouple / break up code at the lowest point possible. 您应该尝试在可能的最低点解耦 / 分解代码。 I think its unlikely that just decoupling each iteration of a loop is enough on the long run. 我认为从长远来看,仅仅解耦循环的每次迭代是不够的。

However, what you really need to do is, to setup an asyncronous runaway timer which gives the implementation enough room to update the UI Queue (or UI thread ). 但是,您真正需要做的是,设置异步失控计时器 ,为实现提供足够的空间来更新UI队列 (或UI线程 )。 This typically is done using methods like setTimeout() (client), nextTick (node.js) or setImmediate (coming soon). 这通常使用setTimeout() (client), nextTick (node.js)或setImmediate (即将推出)等方法完成。

For instance, lets say we have an array, and we want to process each entry 例如,假设我们有一个数组,我们想要处理每个条目

var data = new Array(10000).join( 'data-' ).split('-'); // create 10.000 entries

function process( elem ) {
    // assume heavy operations
    elem.charAt(1) + elem.charAt(2);
}

for(var i = 0, len = data.length; i < len; i++ ) {
    process( data[i] );
}

Now this code is a classic loop, iterating over the array and process its data. 现在这段代码是一个经典循环,遍历数组并处理其数据。 It'll also consume 100% CPU time and will therefore block the browsers UI queue as long as it takes to process all entries (which basically means, the browser UI will freeze and become unresponsive). 它还会消耗100%的CPU时间,因此只要处理所有条目(这基本上意味着浏览器UI将冻结并变得无响应),将阻止浏览器UI队列

To avoid that, we could create a construct like this: 为了避免这种情况,我们可以创建一个这样的结构:

var data  = new Array(10000).join( 'data-' ).split('-'); // create 10.000 entries

function runAsync( data ) {
    var start = Date.now();

    do {
        process( data.shift() );
    } while( data.length && Date.now() - start > 100 );

    if( data.length ) {
        setTimeout( runAsync.bind( null, data ), 100 );
    }
}

runAsync( data.concat() );

What happens here ? 这里发生了什么?

What we're basically doing is: 我们基本上做的是:

  • Take the array and process as much data/entries as possible within a timeframe of 100ms 获取阵列并在100ms的时间范围内处理尽可能多的数据/条目
  • After that, stop processing (call setTimeout ) and give the UI a chance to update 之后,停止处理(调用setTimeout )并为UI提供更新的机会
  • do that as long as we still have data in the array 只要我们仍然在数组中有数据,那就这样做

Any delay above 100 ms is typically recognized by the human eyes as " lag ". 任何超过100毫秒的延迟通常被人眼识别为“ 滞后 ”。 Anything below that seems fluently and nice (at least our eyes will tell us so). 下面的任何东西看起来都很流利和好看(至少我们的眼睛会告诉我们)。 100ms is a good value as limit for maximum processing times. 100ms是一个很好的值,作为最大处理时间的限制。 I'd even suggest to go down to 50ms. 我甚至建议下降到50ms。

The caveat here is that the overall processing time will increase, but I think its a better deal to have longer processing and stay responsive, instead faster processing and a very bad user experience. 需要注意的是, 整体处理时间会增加,但我认为更好的处理是延长处理速度并保持响应速度,而不是更快的处理速度和非常糟糕的用户体验。


Quick Demo: 快速演示:

So you want to limit the number of concurrent asynchronous operations? 那么你想限制并发异步操作的数量? The flaw in your implementation is that you will be deferring each action until the previous one has completed. 您的实施中的缺陷是您将推迟每个操作,直到上一个操作完成。

One option is to use a sequence helper, you could then break this queue up into more manageable chunks for processing. 一种选择是使用序列帮助程序,然后可以将此队列分解为更易于管理的块以进行处理。

https://github.com/michiel/asynchelper-js/blob/master/lib/sequencer.js https://github.com/michiel/asynchelper-js/blob/master/lib/sequencer.js

var actions = [];
$.each(assets, function(key, value) {

    actions.push(function(callback) {
      $.ajax({
          url: 'process.php?id='+val,
          success: function(msg) {

            callback();
          }
        });
    });
  }
);

var sequencer = new Sequencer(actions);
sequencer.start();

If you split your actions array into two arrays, and have them run side by side you would then only ever have two processes running at a time until both queues have completed. 如果将actions数组拆分为两个数组,并让它们并排运行,那么一次只能运行两个进程,直到两个队列都完成为止。

eg 例如

var arr1 = actions.splice(0,100);
var arr2 = actions.splice(100,200);

var sequencer1 = new Sequencer(arr1);
sequencer1.start();

var sequencer2 = new Sequencer(arr2);
sequencer2.start();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在循环完成后以延迟方式返回数据时,如何在for循环中更新数据 - How can I update data in a for loop when my data is returned with a defer after the loop completes 在jQuery中,如何在每个循环中动态删除数组元素? - In jQuery, how can I in an each loop remove array elements dynamically? 如何在jQuery每个循环中保存对上下文的更改? - How can I save changes to the context in a jQuery each loop? 如何在每个循环中随机选择在JQuery中选择的元素 - How can I randomize elements selected in a JQuery each loop 如何在JQuery $ .each循环中将键与字符串进行比较? - How can I compare the key to a string in a JQuery $.each loop? 如何在对象数组上使用 jQuery.each() 循环 - How can I use jQuery.each() loop on Array of Object 如何在OpenCart中推迟或异步javascript - How can I defer or async javascript in OpenCart .each循环内的jQuery .dialog-每次迭代都编写新的对话框内容div-如何在每个循环上销毁旧的div? - jQuery .dialog inside .each loop - new dialog content divs are written on each iteration - how can I destroy the old divs on each loop? 我如何推迟 ES6 promise,如 jquery Deferred? - How do I defer an ES6 promise like jquery Deferred? 如何在此for循环中将EventListener添加到每个innerHTML + =? - How can I addEventListener to each innerHTML += in this for loop?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM