大数组分时加载算法 timedChunk

本篇介绍高性能JavaScript一书作者NicholasC.Zakas提出的大数组的分时加载算法timedChunk

分时加载

分时加载的意义在于分批加载数据确保在数据加载完成后及时的更新UI界面确保用户体验的流畅性。

chunk()


function chunk(array, process, context){
    
    //克隆数组
    var items = array.concat();   
    
    //延时100ms执行
    setTimeout(function(){
        
        var item = items.shift();
        
        //执行`process`方法
        process.call(context, item);
  
        //如果`items`数组不为空,延迟100ms(提供100ms来更新UI界面)然后回调上方的`setTimeout`函数
        if (items.length > 0){
            setTimeout(arguments.callee, 100);
        }
    }, 100);
}




如果该方法的数组大小为100,执行延时为100ms则总耗时长约为10000ms也就是10s。(忽略process执行的时长)
100ms的延时意味着,你花了大部分时间来进行页面UI的更新而且执行JavaScript的时间甚至可能只是几ms或是不到1ms,而且事实上我们并不需要那么长时间。

经过研究发现延时可以降低至25ms,25ms是避免浏览器setTimeout出现问题(IEsetTimeout最小延时15ms左右,也就是说你延时设为0也会在15ms左右的时候执行)。
但是如果你提供了25ms的延时,你要处理上面的数据仅仅大小为100的数组也需要耗时2500ms 2.5s也是很长的一段时间。

timedChunk()

所以NicholasC.Zakas改进了 chunk()

Jakob Nielsen指出JavaScript代码执行时间如果超过100ms持续执行则不能实时的更新页面UI。

NicholasC.ZakasJakob Nielsen的基础上认为JavaScript代码执行时间不应该连续的超过50ms(可以保证流畅的更新UI界面)。

改进算法


//Copyright 2009 Nicholas C. Zakas. All rights reserved.
//MIT Licensed
function timedChunk(items, process, context, callback){
    
    //克隆数组
    var todo = items.concat(); 

    //延时25ms执行
    setTimeout(function(){

        var start = +new Date();
        
        //执行50ms的`process`方法(前提数组足够大)
        do {
             process.call(context, todo.shift());
        } while (todo.length > 0 && (+new Date() - start < 50));
        
        
        //延迟25ms(提供25ms来更新UI界面)然后回调上方的`setTimeout`方法
        if (todo.length > 0){
            setTimeout(arguments.callee, 25);
        } else {
            callback(items);
        }
    }, 25);
}

所以保证了JavaScript的执行时间的是50ms。
每执行50msJavaScript就为UI界面的更新提供了25ms的时间渲染。

参照:

https://threejs.org/examples/?q=sand#raytracing_sandbox

demo

posted @ 2018-09-17 12:05  可爱的黑精灵  阅读(671)  评论(0编辑  收藏  举报