未經授權禁止轉載
1、昂貴計算的處理
在複雜Javascript應用程式開發中,最複雜的可能是使用者介面的單執行緒特性。而Javascript在處理使用者互動時最好的狀況是反應遲鈍,最糟糕的情況是無回應而導致瀏覽器掛起(在Javascript執行時,頁面中所有的更新操作暫停)。源自於這一事實,將所有複雜操作(任何多於100ms的計算)減小到可管理的程度就勢在必行。另外,如果運行了至少5秒鐘還沒有停止,一些瀏覽器(如Firefox 、Opera)將產生一個提示框警告使用者腳本無相應。
這顯然是不可取的,產生一個無回應的介面並不好。但是,幾乎可以肯定的是,當你需要處理大量資料時就會出現這種情況(如處理數以千計的DOM元素會導致這種情況出現)。
此時,計時器就顯得特別有用。由於計時器能有效的暫停Javascript程式碼的執行,它也能阻止瀏覽器將執行的程式碼掛起(只要個別程式碼還不足以讓瀏覽器掛起)。想到這一點,我們可以將正常的、密集的、循環計算納入到非阻塞的計算之中,讓我們看看下面這個例子,這種類型的計算是必要的。
一個長時運行的任務:
<table><tbody></tbody></table>
// Normal, intensive, operation
var table = document.getElementsByTagName("tbody");
for ( var i = 0; i < 2000; i++ ) {
var tr = document.createElement("tr");
for ( var t = 0; t < 6; t++ ){
var td = document.createElement("td");
td.appendChild( document.createTextNode("" + t));
tr.appendChild( td );
}
table.appendChild( tr );
}
}
在這個例子中,我們創建了總數為26000個DOM節點,並將數字填入表中,這太昂貴了,很有可能將瀏覽器掛起以阻止用戶正常的互動。我們可以將計時器引入其中,從而得到與眾不同,也許更好的結果。
用計時器將耗時較長的任務分開來:
<table><tbody></tbody></table>
var table = document.getElementsByTagName("tbody");
var i = 0, max = 1999;
setTimeout(function(){
for ( var step = i + 500; i < step; i++ ) {
var tr = document.createElement("tr");
for ( var t = 0; t < 6; t++ ){
var td = document.createElement("td");
td.appendChild( document.createTextNode("" + t));
tr.appendChild( td );
}
}
table.appendChild( tr );
}
if ( i < max )
setTimeout( arguments.callee, 0 );
}, 0);
在我們修改的例子中,我們將密集的計算分成四個部分,每個創建6500個節點。這些計算不太可能中斷瀏覽器正常的串流。最糟糕的情況也只是這些數字可能隨時調整(例如,使其在250-500之間變化,這樣我們的每個單元將產生3500DOM個節點)。但是,給人印象最深刻的是我們如何改變我們的程式碼以適應新的非同步系統。我們需要做更多的工作以確保元素的數字正確生成(這個循環不會永無止境)。這些代碼與我們初始的很相似。請注意,我們使用閉包維持程式碼片段間的迭代狀態,毫無疑問,不使用閉包,此程式碼將更為複雜。
與原來的技術相比,使用該技術有明顯的變化。瀏覽器的長時掛起被4個視覺化的頁面更新取代。雖然瀏覽器嘗試著盡可能快得去執行這些程式碼片段,但它也在計時器的每一步操作之後渲染DOM變化(就好像大量的更新)。大多數情況下,使用者覺察不到此類型的更新,但記住它們曾經發生過很重要。
有一種情況會使該技術能專門為我服務——我建構的計算大學生日程排列的應用程式。起初,該應用程式是典型的CGI(客戶與伺服器交流,伺服器計算日程表之後將其返回)。但我對它作了改變,講所有的日程計算放到客戶端,這是日程計算的視圖:
這些計算的代價相當昂貴(需要遍歷數以千計的排列才能找到正確的答案)。將日程計算分割成實實在在的單元使這一問題得到了解決(用已經完成的那部分更新用戶界面)。最後,使用者提交的是快速、反應靈敏、可用性較高的使用者介面。
如此有用的技術常常令人驚奇。你會發現它經常被用於長時運行的程式之中,就像測試箱(我們在這章末尾討論它)。更重要的是,這種技術向我們顯示了解決瀏覽器環境的限制是多麼的輕而易舉,同時也為使用者提供了豐富的經驗。