Web Worker 爲 JavaScript 創建多線程環境
主線程可以創建 Worker 線程,並將一些高延遲的任務分配給 Worker 線程在後臺運行
而主線程只會負責渲染和交互,從而保證頁面的流暢性
Web Worker 有兩種類型,分別是 Dedicated Web Worker 和 Shared Web Worker
- Dedicated Web Worker:只有一個頁面可以使用這個 Web Worker
- Shared Web Worker:多個同源頁面可以共享一個 Web Worker,爲跨頁面通信提供一種解決方案
下面介紹 Dedicated Web Worker
主線程通過構造函數 Worker()
,創建一個 Worker 線程,並在參數中指定需要執行的腳本文件
var worker = new Worker('worker.js')
構造函數返回一個 Worker 對象,便於主線程與 Worker 線程通信,Worker 對象常用的屬性和方法如下:
onerror
:用於指定error
事件的監聽函數,當 Worker 發生錯誤時觸發onmessage
:用於指定message
事件的監聽函數,當接收到傳遞的數據時觸發onmessageerror
:用於指定messageerror
事件的監聽函數,當收到的數據無法進行反序列化時觸發postMessage()
:傳遞數據給 Worker 線程terminate()
:終止 Worker 線程
<!DOCTYPE html>
<html>
<head>
<script>
var worker;
function submit() {
if (typeof(Worker) === 'undefined') {
return
}
if (typeof(worker) === "undefined") {
worker = new Worker('worker.js')
}
let input = document.getElementById('data').value
worker.postMessage(input)
worker.onmessage = function(event) {
let result = event.data
document.getElementById('result').innerText = result
worker.terminate()
worker = undefined
}
worker.onerror = function(event) {
console.log('出錯的信息', event.message)
console.log('出錯的文件', event.filename)
console.log('出錯的行數', event.lineno)
console.log('出錯的列數', event.colno)
worker.terminate()
worker = undefined
}
}
</script>
</head>
<body>
<input type="text" id="data" name="data" placeholder="Please Enter Something">
<button onclick="submit()">Reverse String</button>
<span id="result"></span>
</body>
</html>
Worker 線程有一個自己的全局對象,self
和 this
都提供對該對象的引用,這個對象常用的屬性和方法如下:
onmessage
:用於指定message
事件的監聽函數,當接收到傳遞的數據時觸發onmessageerror
:用於指定messageerror
事件的監聽函數,當收到的數據無法進行反序列化時觸發importScripts()
:用於加載其它腳本postMessage()
:傳遞數據給主線程close()
:關閉 Worker 線程
// worker.js
this.onmessage = function(event) {
let data = event.data
let result = reverse(data)
this.postMessage(result)
this.close()
}
function reverse(content) {
return content.split('').reverse().join('')
}
使用 Web Worker 需要注意以下的點:
-
主線程分配給 Worker 線程的腳本文件,不能從本地讀取,它必須來自網絡
-
主線程分配給 Worker 線程的腳本文件,必須與主線程的腳本文件同源,準確來說應該是與頁面文檔同源
-
Worker 線程不能訪問 window、document、parent 對象,但是可以使用 navigator、location 對象
-
Worker 線程不能使用 alert、confirm,但是可以使用 setTimeout、setInterval、XMLHttpRequest
-
主線程和 Worker 線程不能直接通信,必須通過消息傳遞,消息傳遞有兩種方式,一種是拷貝,一種是轉讓
拷貝:拷貝原始數據,產生一份副本,將副本傳遞給目標線程,這種方法在傳遞較大的數據時比較消耗性能
轉讓:將原始數據的所有權轉讓給目標線程,原來線程不再具有這個數據
在默認的實現中,除 ArrayBuffer 外都是拷貝傳遞
【 閱讀更多 HTML 系列文章,請看 HTML學習筆記 】