初識Web Worker

Thoughtful valiant.發表於2018-12-11

第一次瞭解到Web Worker的概念還是在騰訊IVWEB團隊的文章中。今天又在《高效能JavaScript》中讀到,於是打算再記錄一下。共同學習!

1. 前言

起初,在瀏覽器的UI執行緒之外無法執行程式碼。但是Web Worker改變了這種狀況,它引入了一個介面,能使程式碼執行且不佔用瀏覽器UI執行緒的時間。作為HTML5最初的一部分,Web Worker已經被分離出去成為獨立的規範

2. Worker簡介

每個新的Worker都在自己的執行緒中執行程式碼。這意味著Worker執行程式碼不進不會影響瀏覽器UI,也不會影響其他Worker執行的程式碼。

2.1 Worker需要注意什麼?

  • Web Worker沒有繫結UI執行緒,這也意味著它們不能訪問瀏覽器的許多資源。JavaScript和UI共享同一程式的部分原因是它們之間互相訪問頻繁,因此這些任務失控對使用者體驗會是一個災難。

  • Web Worker從外部執行緒種修改DOM會導致使用者介面出現錯誤,但是每個Worker都有自己的全域性執行環境,其功能只是JavaScript特性的一個子集。

2.2 Worker執行環境組成:

  • 一個navigator物件,只包括四個屬性:appNameappVersionuserAgentplatform

  • 一個location物件(與window.location相同,不過所有屬性都是隻讀的)。

  • 一個self物件,指向全域性Worker

  • 一個importScripts()方法,用來載入Worker所用到的外部JavaScript檔案。

  • 所有的ECMAScript物件,諸如:Object、Array、Date等。

  • XMLHttpRequest構造器。

  • setTimeout()setInterval()方法。

  • 一個close()方法,它能立刻停止Worker執行。

由於Web Worker有著不同的全域性執行環境,因此你無法從JavaScript程式碼中建立它。事實上,你需要建立一個完全獨立的JavaScript檔案,其中包含了需要在Worker中執行的程式碼。要建立Worker執行緒,必須傳入這個JavaScript檔案的URL,例如: let worker = new Worker('workerCode.js');

*此程式碼一旦執行,將為這個檔案建立一個新的執行緒和一個新的Worker執行環境。該檔案會被非同步下載,直到檔案下載並執行完成後才會啟動此Worker

3. 與Worker通訊

網頁程式碼可以通過postMessage()方法給Worker傳遞資料,它接收一個引數,即需要傳遞給Worker的資料。此外,Worker還有一個用來接收資訊的onmessage時間處理器。例如:

let worker = new Worker('workerCode.js');
woeker.onmessage = function (event) {
  alert(event.data);
}
worker.postMessage('Li');
複製程式碼

Worker通過出發message事件來接收資料。定義onmessage事件處理器後,該事件物件就具有一個data屬性用於存放傳入的資料。Worker可通過它自己的postMessage()方法把資訊回傳給頁面:

// workerCode.js檔案
self.onmessage = function (event) {
  self.postMessage(event.data + 'is a student.');
}
複製程式碼

*最終的字串在Workeronmessage事件處理器中構造完成,訊息系統是網頁和Worker通訊的唯一途徑。

4. Worker載入外部檔案

Worker通過importScripts()方法載入外部JavaScript檔案,該方法接收一個或多個JavaScript檔案URL作為引數。importScripts()的呼叫過程是阻塞式的,直到所有檔案載入並執行完成之後,指令碼才會繼續執行。由於Worker在UI執行緒之外執行,所以這種阻塞並不會影響UI相應。例如:

// workerCode.js檔案
importScripts('importFile1.js', 'importFile2.js');

self.onmessage = function (event) {
  self.postMessage('Hello' + event.data + '!');
}
複製程式碼

這段程式碼第一行中引入了兩個JavaScript檔案,它們將在Worker執行緒的上下文中用到。

5. Worker實際應用

Worker適用於那些處理純資料,或者與瀏覽器UI無關的長時間執行指令碼。比如:

  • 編碼/解碼大字串。
  • 複雜數學運算(包括影像或視訊處理)。
  • 大陣列排序。

任何超過100ms的處理過程,都應當考慮Worker方案是不是比基於定時器方案更為合適。比如:

解析一個很大的JSON字串。假設資料量足夠大,至少需要500ms才能完成解析。很明顯時間太長了,超出了客戶端允許JavaScript執行的時間,因為它會干擾使用者體驗。而此任務難以分解成若干個使用定時器的小任務,因此Worker成為最理想的解決方案。

當然Web Worker肯定還有更多其它用處,發揮它更強的作用。


如果有什麼錯誤請各位指出,感謝!

相關文章