瀏覽器使用單線程從隊列中取出事件,而後對事件自己進行處理或執行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); }