多線程的JavaScript: Web Worker
Web Worker是 HTML5推出的標準
Web Workers makes it possible to run a script operation in a background thread separate from the main execution thread of a web application.
優點
允許 JavaScript 腳本創建多個線程,從而充分利用 CPU 的多核計算能力,不會阻塞主線程 (一般指 UI 渲染線程) 的運行, 兼容性良好,基本覆蓋了所有主流瀏覽器
局限
Web Worker本質上沒有突破JS的單線程的性質,Web Worker腳步不能直接操作DOM節點, 不能使用絕大多數的BOM API。 上下文環境是DedicatedWorkerGlobalScope 而不是Window。 運行Worker的實際上是一個沙箱,跑的是與主線程完全獨立的JavaScript文件。
使用場景
作為主線程的附屬,完成高 CPU 計算型的數據處理,再通過線程間通信將執行結果傳回給主線程。在整個過程中,主線程仍然能正常地相應用戶操作,從而很好地避免頁面的卡頓現象。
具體場景:
- 預加載數據:可以使用Worker提前加載數據,實現秒開
- 拼寫檢查
- 加密: 有時候加密會非常耗時。
- 漸進式網絡應用PWA: 例如:通過與IndexDB的整合實現離線訪問
如何使用
新建
const worker = new Worker("./worker.js");
通信
// main.js
const worker = new Worker("./worker.js");
// 主線程發送消息
worker.postMessage({ data: '黃某還是挺不錯的' });
// 主線程接收消息
worker.onmessage = (e) => {
const { data } = e;
if (!data) return;
console.log(data);
}
// worker.js
// worker線程接收消息
self.addEventListener('message', (e) => {
const { data } = e;
if (!data) return;
// worker線程發送消息
self.postMessage({data: 'worker received data'})
});
注: Worker 中,this.xx, self.xx 與直接使用 xx,其作用域都指向 worker 的全局變量 DedicatedWorkerGlobalScope ,可以互換
銷毀
兩種方式
// 第一種:主線程通知銷毀
// main.js
worker.terminate();
// worker.js
self.close();
Worker加載腳本
importScripts('script1.js');
// 或者可以加載多個
importScripts('script1.js', 'script2.js');
錯誤處理
主線程可以監聽Worker是否發生錯誤
worker.onerror(function (event) {
console.log([
'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
].join(''));
});
// 內部也可以監聽error事件
worker.addEventListener('error', function (event) {
// ...
});
參考:
- 給 JavaScript 插上多線程的翅膀 —— Web Worker 的 Promise 化實踐:http://www.alloyteam.com/2020/07/14645/
- 阮一峰網絡日志Web Worker使用教程 http://www.ruanyifeng.com/blog/2018/07/web-worker.html
- 微信小程序多線程Workerhttps://developers.weixin.qq.com/miniprogram/dev/framework/workers.html
- uniapp Worker: https://uniapp.dcloud.io/api/worker
dev/framework/workers.html)
- uniapp Worker: https://uniapp.dcloud.io/api/worker

浙公網安備 33010602011771號