gpt4 book ai didi

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

转载 作者:可可西里 更新时间:2023-11-01 01:23:31 27 4
gpt4 key购买 nike

我在 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com