概述
我們都知道JavaScript是一門單線程語言,其單線程帶來了很大的不便。Web Worker的出現就是爲JavaScript創造多線程的環境,運行主進程創建Worker線程,將一些任務分配給Worker線程運行。主線程運行的同時,Worker線程在後臺運行,兩者互不干擾。Worker線程計算的結果返回給主線程,這樣主線程在面對計算密集型或高延遲的任務,就會比較流暢。
Web Worker的特點
- Worker線程一旦創建成功,就會始終運行。即使主線程卡死,它依然在運行。這樣有利於與主線程通信,但是這也造成了Worker比較浪費資源,所以,一旦用完,我們就應該關閉它。
- 同源限制: 分配給Worker線程運行的腳本文件,必須與主線程的腳本文件同源
- DOM限制: 不能操作主線程中的DOM,要保持DOM的唯一性。
document
、window
、parent
這些對象都無法使用。可以使用navigator
、lacation(只讀)
、XMLHttpRequest
、setTimeout
等API。 - 腳本限制: Worker線程不能執行
alert()、confirm()
這些方法。但可以使用 XMLHttpRequest 對象發出 AJAX 請求。 - 文件限制: 不可以讀取本地文件(js主線程也不能)。出於安全性考慮,瀏覽器不允許js讀取本地文件。
- 兩類線程: Web Worker定義了兩類工作線程:
專用線程
(只有一個頁面可以使用這個線程)與共享線程
(多個同源頁面可以共享一個線程)。
基本使用
主線程
-
創建Web Worker
主線程採用
new
命令,調用Worker()
構造函數,創建一個Worker線程:var worker = new Worker('work.js');
Worker()
構造函數的參數是一個腳本文件,該文件就是Worker線程要執行的任務, -
向Web Worker發送消息
主線程採用
worker.postMessage()
方法,向Worker發消息。worker.postMessage('hello'); worker.postMessage( {number: 10})
worker.postMessage()
中的參數,就是主線程傳給Worker的數據。它可以是任意類型,包括二進制 -
主進程接受子線程發回的消息
worker.onmessage = function(event) { console.log('received worker message' + event.data); } // 或者 Worker.addEventListener('message', event => { console.log('received worker data', event.data); }, false);
-
主進程監聽Worker是否發生錯誤
如果發生錯誤,Worker 會觸發主線程的error事件。
worker.onerror(function (event) { // ... }) // 或者 worker.addEventListener('error', function (event) { // ... });
-
主線程關閉線程
Worker完成任務之後,主進程就可以關閉它。
worker.terminate();
Worker線程
-
監聽來自主線程的數據
self.addEventListener('message' ,function(event) { self.postMessage('You said:' event.data); },false); // 等同於 this.addEventListener('message' ,function(event) { this.postMessage('You said:' event.data); },false);
self
表示子線程自身,當然也可以使用self.onmessage
來監聽。self.postMessage()
方法用來向主線程發送消息。 -
Worker自身關閉
Worker線程可以在內部自己關閉,使用
close()
方法。 -
Worker加載腳本
Worker內部如果要加載其他腳本,有一個專門的方法
importScripts()
。importScripts('script1.js'); // 可以同時加載多個腳本 importScripts('script1.js', 'script2.js');
使用場景
- 數學運算
Web Worker最簡單的應用就是用來做後臺計算,對CPU密集型的場景再適合不過了。 - 圖像處理
通過使用從<canvas>
中獲取的數據,可以把圖像分割成幾個不同的區域並且把它們推送給並行的不同Workers來做計算,對圖像進行像素級的處理,再把處理完成的圖像數據返回給主頁面。 - 大數據的處理
目前mvvm框架越來越普及,基於數據驅動的開發模式也越愈發流行,未來大數據的處理也可能轉向到前臺,這時,將大數據的處理交給在Web Worker也是上上之策了吧。
常用API總結
主線程中的API:
- worker.postMessage(): 主線程往worker線程發消息,消息可以是任意類型數據,包括二進制數據
- worker.terminate(): 主線程關閉worker線程
- worker.onmessage(): 指定worker線程發消息時的回調,也可以通過worker.addEventListener(‘message’,cb)的方式
- worker.onerror: 指定worker線程發生錯誤時的回調,也可以worker.addEventListener(‘error’,cb)
Worker線程中的API:
- self.postMessage: worker線程往主線程發消息,消息可以是任意類型數據,包括二進制數據
- self.close: worker線程關閉自己
- self.onmessage: 指定主線程發worker線程消息時的回調,也可以self.addEventListener(‘message’,cb)
- self.onerror: 指定worker線程發生錯誤時的回調,也可以 self.addEventListener(‘error’,cb)
參考文章: