m90*_*m90 16 javascript jquery underscore.js
我在每个循环的jQuery中进行"重"画布操作,导致较慢的设备(IE和iPad)有时变得完全没有响应.
所以我想我可以使用下划线_.defer()来排列每个循环中的函数,如:
function handleAsset = _.defer(function(){
//weightlifting goes here (partly async)
});
$.each(assets, handleAsset);
Run Code Online (Sandbox Code Playgroud)
然而,这会抛出一个奇怪的错误(堆栈跟踪指向$.each):
Uncaught TypeError: Object 20877 has no method 'call'
Run Code Online (Sandbox Code Playgroud)
这种做法有缺陷吗?这是由于处理程序函数内部的异步操作吗?还有另一种/更好的方法来实现这一目标吗?
jAn*_*ndy 22
它有缺陷.您应该尝试在可能的最低点解耦/分解代码.我认为从长远来看,仅仅解耦循环的每次迭代是不够的.
但是,您真正需要做的是,设置异步失控计时器,为实现提供足够的空间来更新UI队列(或UI线程).这通常使用setTimeout()(client),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] );
}
Run Code Online (Sandbox Code Playgroud)
现在这段代码是一个经典循环,遍历数组并处理其数据.它还会消耗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() );
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?
我们基本上做的是:
setTimeout)并为UI提供更新的机会任何超过100毫秒的延迟通常被人眼识别为" 滞后 ".下面的任何东西看起来都很流利和好看(至少我们的眼睛会告诉我们).100ms是一个很好的值,作为最大处理时间的限制.我甚至建议下降到50ms.
需要注意的是,整体处理时间会增加,但我认为更好的处理是延长处理速度并保持响应速度,而不是更快的处理速度和非常糟糕的用户体验.
快速演示:
| 归档时间: |
|
| 查看次数: |
1945 次 |
| 最近记录: |