本週 JavaScript 436期週報連接。這裏面主要我想談談 WebWorker 相關的內容。javascript
衆所周知,JavaScript 使用運行在單線程上的。可是 JavaScript 能夠處理異步代碼,其中 Ajax 就是個很好的例子。異步帶來的用戶體驗沒必要多說,可是這裏有個問題:若是異步以後的成功回調是一次密集 CPU 操做。那麼原本由於異步而產生的非阻塞用戶體驗,就又會由於沒法從事件循環出解脫而又產生阻塞。對用戶而言便又產生了不響應的 UI。這種狀況,咱們能夠認爲 JavaScript 只是解決了單線程的部分限制。能夠假設,若是咱們把這一次密集 CPU 操做也在異步中執行,那麼用戶體驗仍然一如既往地流暢。html
Web Worker 就應用而生了。前端
Web Worker 是真正的多線程。java
Web Worker並不會阻塞事件循環。參考這個 demo 能夠看到在 5 萬條數據排序的時候,使用 WebWorker 帶來的體驗差異。Web Worker 並非 JavaScript 的一部分,它是經過 JavaScript 能夠訪問的瀏覽器特性。然而,Web Worker 並無在 Node.js 中實現,有點像子進程的概念,可是卻有不一樣。git
Web Worker是有三種類型,在 MDN 中有詳細定義:github
其中,專用 Workers 是經過主進程實例化,也只能經過主進程通訊;共享 Workers 能夠訪問全部同源的進程(在不一樣的瀏覽器標籤,窗口或者其餘的共享 Workers);服務 Workers 是針對源和路徑的事件驅動 worker,用在網絡不可用的狀況下,能夠控制網站和相關站點,插入和修改導航和資源請求,緩存資源等。web
Web Workers 在瀏覽器中運行一個獨立的線程。正因如此,執行的代碼須要被包含在一個獨立的文件中,這一點比較重要。使用方式也很簡單:瀏覽器
var worker = new Worker('taks.js');
複製代碼
瀏覽器會建立一個異步下載的文件線程。當下載完成後,會被執行。經過調用 postMessage
方法來使用建立好的 worker。它可讓一個 Web Worker 和頁面之間通訊。緩存
比較新的瀏覽器支持 JSON 做爲第一個參數,而舊的瀏覽器只支持字符串。安全
<button onclick="startComputation()">Start computation</button>
<script> function startComputation() { worker.postMessage({'cmd': 'average', 'data': [1, 2, 3, 4]}); } var worker = new Worker('doWork.js'); worker.addEventListener('message', function(e) { console.log(e.data); }, false); </script>
複製代碼
在 new 一個 Worker 以後,給它的實例註冊一個叫 message
的監聽事件。同時在咱們的 doWork.js
裏,也要註冊相同事件用來處理數據。
self.addEventListener('message', function(e) {
var data = e.data;
switch (data.cmd) {
case 'average':
var result = calculateAverage(data); // Some function that calculates the average from the numeric array.
self.postMessage(result);
break;
default:
self.postMessage('Unknown command');
}
}, false);
複製代碼
當消息到達的時候,worker 就開始執行計算,具體來講運行 calulateAverage
方法。結束以後,把結果傳遞給主頁面。在 worker 的上下文環境中,self
和 this
都是 worker 的全局,與 window 無關。有兩種方式能夠結束 worker: worker.terminate()
和 self.close()
。
navigator
對象location
對象(只讀)XMLHttpRequest
setTimeout()/clearTimeout()
和 setInterval()/clearInterval()
importScripts()
導入外部腳本window
對象document
對象parent
對象光線追蹤
爲了模擬光線路徑,這種場景是須要大量計算的,可是不能再每次大量計算的時候就讓光線變得卡頓或者不天然,這時候workers 就能夠發揮做用了。
加密
也是純粹的計算工做,交給 web workers 正當其用。並且有些加密解密的操做是至關消耗時間的。
預加載數據 當網絡不是很穩定的時候,能夠先把數據取出來存在本地瀏覽器緩存中,這樣在須要的時候就會減小延遲感
拼寫檢查
若是對應的檢查數據是一本字典的話。這種場景下,使用 web worker 就十分必要了。
總結一下使用 Web Workers 的場景的共同點:
Web Worker 是個瀏覽器實現的特性,儘管如此,咱們仍是可以在某些地方發揮它的優點去加強用戶體驗,遵循「漸進加強,平穩退化」得原則。沒有理由去拒絕使用它。但其實,Web Worker 的使用場景也十分具備特色,它應該不是做爲解決卡頓問題的首選,由於在前端,除了動畫之外每每沒有特別大的計算量。大多數的不流暢用戶體驗,多半是重繪和重排沒有優化好而引發的,千萬不可緣木求魚,爲了 Web Worker 什麼都往上鼓搗。