WebWorker 簡單使用方式

Javenn發表於2018-12-28

WebWorker 一定程度上可以算得上是瀏覽器中的多執行緒技術了,在專案中適當使用 Worker 來做一些耗時的操作能大大提高頁面整體流暢度。

Worker的使用也是非常簡單的,通過向 Worker 建構函式傳遞需要在worker中執行的檔案路徑作為引數,就可以使得對應的檔案執行在worker執行緒。

Worker執行緒中沒有 window 物件,也沒有 document 物件。既不能操作也不能建立 DOM。而且 worker 執行緒和主執行緒只能通過訊息機制來通訊。

下面是一個 WebWorker 的簡單用法:

首先需要建立一個 Worker 例項:

var worker = new Worker('worker.js');

在 worker.js 中寫下如下程式碼:

1 console.log('Hello world');

然後 worker.js 就會在 worker 執行緒中執行,這也就意味著這裡的程式碼不管是什麼,基本上可以認為對主執行緒(也就是瀏覽器執行緒)沒有任何影響。雖然實際上電腦跑的東西越多效能越差,但至少主執行緒不會被阻塞。

無法跟主執行緒互動的程式碼用處非常有限,當然,你可以繞過去,直接大家都走伺服器端結合 WebSocket 來實現跟主執行緒,但 WebWorker 本身能跟主執行緒通過訊息機制來互動確實會更方便些,如果再允許提交對於 DOM 的操作就更好了。

WebWorker 通過 postMessage 來傳送訊息,通過 message 事件來接受接收訊息。其中傳送的資料就在 event.data 中。

比如上面的程式碼,由於 worker.js 是通過主執行緒的程式碼載入的,所以執行順序定然晚於主執行緒的程式碼執行,當 worker.js 中的程式碼執行後,可以通過向主執行緒傳送一個訊息,告訴主執行緒一切就緒,可以開始開始正常互動了.

這裡需要知道的就是 在 worker 中沒有 window 例項,也沒有全域性的 this,但是卻有著 WorkerGlobalScope 也就是 self,當前 worker 自己。

1 self.postMessage('ready');

在主執行緒中通過事件處理程式接收訊息

1 worker.addEventListener('message', function (event) {
2     console.log(event.data);
3 });

另外,所有跟 worker 執行緒互動的程式碼也最好在收到 ·ready· 這個訊息之後進行。因為此時 worker 執行緒已經就緒,而且可以在傳送 ready 訊息之前把必備的準備工作做好。

還有就是訊息不要真的就傳送簡單的字串,除非系統裡面確實就是這種需求,最好設計下資料結構,採用統一的方式來做訊息互動,比如類似下面這樣或者別的方式都行:

{
    cmd: '',
    payload: ...
}

要進行錯誤處理,在主執行緒和在 worker 中做法很相似,都是新增 “error”事件處理程式,不同的是用 worker 例項還是 WorkerGlobalScope 也就是 self。

1 worker.addEventListener('error', function (event) {
2     console.log('在主執行緒內監聽 worker 例項的錯誤');
3 });
4 
5 self.addEventListener('error', function (event) {
6     console.log('在 worker 執行緒內監聽當前 worker 的錯誤');
7 });

類似在 html 文件中可以使用 <script> 標記匯入外部指令碼,在 worker 裡面也可以匯入外部指令碼,用法如下:

1 importScripts('script1.js', 'script2', ....);  // 可以匯入一個到多個,省略號不是程式碼,這行只算是虛擬碼

最後用完了 worker 就可以把它關閉了,在主執行緒中用 terminate,在 worker 執行緒中直接用用 close 就可以了,用不到時就應該即使關閉,多少能省點系統資源。

1 worker.terminate(); // 在主執行緒中關閉當前 worker
2 self.close(); // 在 worker 中關閉自己

 

相關文章