优化前的版本:leti=0;letstart=Date.now();functioncount(){//做繁重的工作for(letj=0;j<1e9;j++){i++;}alert("完成时间"+(Date.now()-start)+'ms');}count();上面count函数中for循环中i的累加,是一个CPU密集型任务。在执行完成之前,JavaScript引擎任务队列中的其他任务是没有机会执行的。优化后的版本将累加i从1到1e9的任务分解为1000个小子任务。每个子任务执行完后,调用setTimeout对自己进行调度,让任务队列中的其他任务有机会执行。leti=0;letstart=Date.now();functioncount(){//做一件繁重的工作(*)do{i++;}while(i%1e6!=0);if(i==1e9){alert("完成时间"+(Date.now()-start)+'ms');}else{setTimeout(计数);//安排新呼叫(**)}}count();第一轮任务执行:i=1...1000000第二轮任务执行:i=1000001..2000000以此类推。现在,如果在引擎忙于执行第1部分时出现新的辅助任务(例如onclick事件),它将排队,然后在第1部分完成后执行,然后再执行下一部分。在计数执行之间,使用setTimeout定期返回事件循环,让JavaScript引擎有机会安排其他任务执行以响应其他用户操作。leti=0;letstart=Date.now();functioncount(){//把调度移到开头if(i<1e9-1e6){setTimeout(count);//安排新呼叫}do{i++;}while(i%1e6!=0);if(i==1e9){alert("完成时间"+(Date.now()-start)+'ms');}}数数();for浏览器脚本拆分CPU密集型任务的另一个好处是我们可以显示进度指示器。如前所述,对DOM的更改只会在当前运行的任务完成后绘制,无论当前运行的任务需要多长时间才能完成。这是一个示例:
