JavaScript 語言采用的是單線程模型,也就是說,所有任務隻能在一個線程上完成,一次隻能做一件事。前面的任務沒做完,後面的任務隻能等着。随着電腦計算能力的增強,尤其是多核 CPU 的出現,單線程帶來很大的不便,無法充分發揮計算機的計算能力。
Web Worker 的作用,就是為 JavaScript 創造多線程環境,允許主線程建立 Worker 線程,将一些任務配置設定給後者運作。在主線程運作的同時,Worker 線程在背景運作,兩者互不幹擾。等到 Worker 線程完成計算任務,再把結果傳回給主線程。這樣的好處是,一些計算密集型或高延遲的任務,被 Worker 線程負擔了,主線程(通常負責 UI 互動)就會很流暢,不會被阻塞或拖慢。
Worker 線程一旦建立成功,就會始終運作,不會被主線程上的活動(比如使用者點選按鈕、送出表單)打斷。這樣有利于随時響應主線程的通信。但是,這也造成了 Worker 比較耗費資源,不應該過度使用,而且一旦使用完畢,就應該關閉。
Web Worker 有以下幾個使用注意點。
(1)同源限制
配置設定給 Worker 線程運作的腳本檔案,必須與主線程的腳本檔案同源。
(2)DOM 限制
Worker 線程所在的全局對象,與主線程不一樣,無法讀取主線程所在網頁的 DOM 對象,也無法使用document、window、parent這些對象。但是,Worker 線程可以navigator對象和location對象。
(3)通信聯系
Worker 線程和主線程不在同一個上下文環境,它們不能直接通信,必須通過消息完成。
(4)腳本限制
Worker 線程不能執行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 對象發出 AJAX 請求。
(5)檔案限制
Worker 線程無法讀取本地檔案,即不能打開本機的檔案系統(file://),它所加載的腳本,必須來自網絡。
基本用法
1.主線程
主線程采用new指令,調用Worker()構造函數,建立一個 Worker 線程。
Worker()構造函數的參數是一個腳本檔案,該檔案就是 Worker 線程所要執行的任務。
然後,主線程調用worker.postMessage()方法,向 Worker 發消息。
worker.postMessage('Hello World');
worker.postMessage({method: 'echo', args: ['Work']});
worker.postMessage()方法的參數,就是主線程傳給 Worker 的資料。它可以是各種資料類型,包括二進制資料。
接着,主線程通過worker.onmessage指定監聽函數,接收子線程發回來的消息。
worker.onmessage = function (event) {
console.log('Received message ' + event.data);
doSomething();
}
function doSomething() {
// 執行任務
worker.postMessage('Work done!');
}
主線程可以監聽 Worker 是否發生錯誤。如果發生錯誤,Worker 會觸發主線程的error事件。
worker.onerror(function (event) {
console.log([
'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
].join(''));
});
// 或者
worker.addEventListener('error', function (event) {
// ...
});
2.Worker 線程
Worker 線程内部需要有一個監聽函數,監聽message事件。
self.addEventListener('message', function (e) {
self.postMessage('You said: ' + e.data);
}, false);
上面代碼中,self代表子線程自身,即子線程的全局對象。是以,等同于下面兩種寫法。
// 寫法一
this.addEventListener('message', function (e) {
this.postMessage('You said: ' + e.data);
}, false);
// 寫法二
addEventListener('message', function (e) {
postMessage('You said: ' + e.data);
}, false);
除了使用self.addEventListener()指定監聽函數,也可以使用self.onmessage指定。
self.postMessage()方法用來向主線程發送消息。
self.close()用于在 Worker 内部關閉自身。
以上隻是記錄。
http://www.ruanyifeng.com/blog/2018/07/web-worker.html