首页 » 编写高质量代码:改善JavaScript程序的188个建议 » 编写高质量代码:改善JavaScript程序的188个建议全文在线阅读

《编写高质量代码:改善JavaScript程序的188个建议》建议121:使用定时器限时运行代码

关灯直达底部

有时每次只执行一个任务,这样效率不高。考虑这样一种情况:处理一个拥有1000项的数组,每处理一项需要1 ms。如果在每个定时器中处理一项,在两次处理之间间隔25 ms,那么处理此数组的总时间是(25+1)×1000=26 000 ms,也就是26 s。如果每批处理50个,每批之间间隔25 ms,那么结果会怎么样呢?

整个处理过程变成(1000/50)×25+1000=1500 ms,也就是1.5 s,而且用户也不会察觉界面阻塞,因为最长的脚本运行只持续了50 ms。通常批量处理比每次处理一项速度更快。

如果记住JavaScript可连续运行的最大时间是100 ms,那么可以优化先前的模式。建议将这个数字削减一半,不要让任何JavaScript代码持续运行超过50 ms,这只是为了确保代码永远不会影响用户体验。可通过原生的Date对象跟踪代码的运行时间,这是大多数JavaScript分析工具所采用的工作方式,例如:


var start=+new Date,stop;

someLongProcess;

stop=+new Date;

if(stop-start<50){

alert("Just about right.");

}else{

alert("Taking too long.");

}


由于每个新创建的Data对象都以当前系统时间初始化,因此可以周期性地创建新Data对象并比较它们的值,以获取代码运行时间。通过加号(+)将Data对象转换为一个数字,这样在后续的数学运算中就不必再转换了。这一技术也可用于优化以前的定时器模板。timedProcessArray方法通过一个时间检测机制可在每个定时器中执行多次处理,例如:


function timedProcessArray(items,process,callback){

var todo=items.concat;

setTimeout(function{

var start=+new Date;

do{

process(todo.shift);

}while(todo.length>0&&(+new Date-start<50));

if(todo.length>0){

setTimeout(arguments.callee,25);

}else{

callback(items);

}

},25);

}


此函数中添加了一个do-while循环,它在处理完每个数组项后检测时间。在定时器函数运行时,因为数组中存放了至少一个项,所以后对循环进行测试比先测试更合理。在Firefox 3中,如果process是一个空函数,处理一个1000项的数组需要34~38 ms,那么原始的timedProcessArray函数处理同一个数组需要超过25 000 ms。这就是定时任务的作用,避免将任务分解成过于琐碎的片断。