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

标签 javascript jquery underscore.js

我在 jQuery 中执行“繁重”的 Canvas 操作,每个循环导致较慢的设备(IE 和 iPad)有时变得完全没有响应。

所以我想我可以使用下划线的 _.defer() 来对每个循环中的函数进行排队,例如:

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

$.each(assets, handleAsset);

但这会引发一个奇怪的错误(堆栈跟踪指向 $.each):

Uncaught TypeError: Object 20877 has no method 'call'

这种方法有缺陷吗?这是由于处理函数内部正在进行异步操作吗?是否有另一种/更好的方法来实现这一目标?

最佳答案

这是有缺陷的。您应该尝试在可能的最低点解耦/分解 代码。我认为从长远来看,仅仅解耦循环的每次迭代不太可能就足够了。

但是,您真正需要做的是设置一个异步失控计时器,它为实现提供了足够的空间来更新UI 队列(或UI线程)。这通常是使用 setTimeout()(客户端)、nextTick (node.js) 或 setImmediate(即将推出)等方法完成的。

例如,假设我们有一个数组,我们想要处理每个条目

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

现在这段代码是一个经典的循环,遍历数组并处理它的数据。它还会消耗 100% 的 CPU 时间,因此会阻塞浏览器 UI 队列,只要处理所有条目(这基本上意味着,浏览器 UI 将卡住变得 react 迟钝)。

为了避免这种情况,我们可以创建一个这样的结构:

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

这里发生了什么?

我们基本上做的是:

  • 获取数组并在 100 毫秒
  • 的时间范围内处理尽可能多的数据/条目
  • 之后,停止处理(调用setTimeout)并给UI一个更新的机会
  • 只要数组中还有数据就这样做

任何超过 100 毫秒 的延迟通常被人眼识别为“滞后”。下面的任何内容看起来都很流畅和漂亮(至少我们的眼睛会告诉我们)。 100 毫秒作为最大处理时间的限制是一个很好的值。我什至建议减少到 50 毫秒。

这里需要注意的是,整体处理时间会增加,但我认为处理时间更长并保持响应速度更好,而不是处理速度更快和非常糟糕的用户体验。


快速演示:

关于javascript - 我怎样才能推迟每个循环的jQuery,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13955976/

相关文章:

javascript - 哪些 jQuery 事件不冒泡?

javascript - Java 使用 XMLHttpRequest 的编码问题

javascript - 如何阻止表单在提交时重置

javascript - 来自多个来源的 jQuery 动画 - 影响多个对象

javascript - 下划线 map 对象

javascript - 在 node.js 或 JavaScript 中映射数组的简洁方法

javascript - Backbone.js 相当于 django humanize - int.word 和 int.comma - 使用 underscore.string

javascript - JS 获取字符串最后一个点并返回其后面的字符串

javascript - 简单的 GET 请求需要很多时间才能返回

javascript - 如何检查焦点是否离开一组元素