这是有缺陷的。您应该尝试在可能的最低点解耦/分解代码。我认为从长远来看,仅仅解耦循环的每次迭代就足够了。
但是,您真正需要做的是,设置一个异步失控计时器,为实现提供足够的空间来更新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 将冻结并变得无响应)。
为了避免这种情况,我们可以创建一个这样的结构:
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 毫秒的延迟通常都会被人眼识别为“滞后”。任何低于它的东西看起来都很流畅和漂亮(至少我们的眼睛会这样告诉我们)。100ms 是一个很好的值作为最大处理时间的限制。我什至建议降低到 50 毫秒。
这里需要注意的是整体处理时间会增加,但我认为处理时间更长并保持响应更好,而不是更快的处理和非常糟糕的用户体验。
快速演示: