有時每次只執行一個任務,這樣效率不高。考慮這樣一種情況:處理一個擁有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。這就是定時任務的作用,避免將任務分解成過於瑣碎的片斷。