高性能網站建設讀書筆記(3)建立快速響應的Web應用

建立快速響應的Web應用

瀏覽器使用單線程從隊列中取出事件,而後對事件自己進行處理或執行JavaScript。所以,瀏覽器每次只能處理這些任務中的一個,而且任意一個任務都能阻止其餘任務執行。
html

怎樣纔算足夠快

響應時間準則
瀏覽器

0.1秒 :用戶直接操做UI中對象的感受極限。如,從用戶選擇表格中一列到該列高亮的時間間隔。理想狀況下,也是對列進行排序的響應時間。
多線程

1秒:用戶隨意地在計算機指令空間進行操做而無需過分等待的感受極限。超過一秒的延遲要提示用戶計算機正在解決這個問題,如改變光標形狀。函數

10秒:用戶專一於任務的極限。超過十秒的任何操做須要一個百分比完成指示器,以及一個方便用戶中斷操做且有清晰標識的方法。假設用戶遭遇超過10秒延遲後才返回原UI的狀況,他們須要從新適應。在用戶工做中,超過10秒的延遲僅在天然中斷時能夠接受,好比切換任務時。post

測量延遲時間

手動代碼檢測
性能

<div onclick="myJavaScriptFunction()">...</div>
function myJavaScriptFunction() {
    var start = new Date().getMilliseconds();
    //這是開銷大的代碼
    var executionTime = stop - start;
    alert("myJavaScriptFunction() executed in " + executionTime + 
        " milliseconds");
}

自動代碼檢測(性能分析)優化

Firefox的插件Firebug包含JavaScript代碼性能分析器。
google

但事實上性能分析器也會受到外在的影響,觀察代碼性能的行爲改變了代碼的性能。
spa

能夠在網頁界面上執行一個高級別的任務(如單擊發送按鈕),而後執行Firebug性能分析器去查看哪些函數消耗的執行時間最多,最後集中在這些函數上進行優化工做。
插件

當延遲變得很嚴重時

若是JavaScript代碼使瀏覽器線程停滯過長時間,大多瀏覽器會進行干預並給用戶中斷執行代碼的機會。

what determine that a script is long running

結論:別把運行時間可能很長的低性能代碼引入到網頁中。

線程處理

JavaScript不支持多線程。

Brendan Eich JavaScript創立者,Mozilla首席技術官

確保響應速度

2.4.1 Web Workers

 

//建立並開始執行worker
var worker = new Worker("js/decrypt.js")
//註冊事件處理程序,當worker給主線程發送信息時執行
worker.onmessage = function(e){
    alert("The decrpyted value is " + e.data);
}
//發送信息給worker,這裏是指待解密的值
worker.postMessage(getValueToDecrypt());

js/decrypt.js

//註冊用來接收自主線程信息的處理程序
onmessage = function(e){
    //獲取傳過來的數據
    var valueToDecrypt = e.data;
    //TODO: 這裏實現解密功能
    
    //把值返回給主線程
    postMessage(decryptedValue);
}

在頁面上任何開銷大的(長時間運行)JavaScript操做都應該委託給Worker,這將使得應用程序快速運行。

2.4.2 Gears

若是發現瀏覽器不支持Web Worker API還有替代方案。

Google 的Gears插件,你能夠利用他在IE、Firefox、Safari的早期版本上實現像Web Workers同樣的功能。

Gears Worker API 與 Web Worker API類似但不徹底一致。

//建立Worker Pool,他會生產Worker
var workerPool = google.gears.factory.create('beta.workerpool');
//註冊事件處理程序,它接受來自Worker的信息
workerPool.onmessage = function(ignore1, ignore2, e){
    alert("The decrypted value is " + e.body);
}
//建立Worker
var workerId = workerPool.createWorkerFromUrl("js/decrypt.js")
//發送信息到這個Worker
workerPool.sendMessage(getValueToDecrypt(),workerId);

js/decrypt.js

var workerPool = google.gears.workerPool;
workerPool.onmessage = function(ignore1, ignore2, e){
    //獲取傳過來的數據
    var valueToDecrypt = e.body;
    //TODO: 這裏實現解封功能
    
    //把值返回給主線程
    workerPool.sendMessage(decryptedValue, e.sender);
}
相關文章
相關標籤/搜索