Web Workers 使用指南
文章目录
- 前言
- 基础使用
- 高级特性
- 使用 ES Modules
- 实际应用场景
- 图像处理
- 大数据处理
- 轮询任务
- 性能优化技巧
- 现代开发方式
- 使用 worker-loader (Webpack)
- Vite中的Worker使用
- 限制与注意事项
- DOM限制:
- 通信限制:
- 同源策略:
- 最佳实践
前言
Web Workers 是浏览器提供的 JavaScript 多线程解决方案,允许在后台线程中运行脚本,避免阻塞主线程。
基础使用
创建 Worker// 主线程代码
const worker = new Worker('worker.js');// worker.js (Worker线程)
self.onmessage = function(e) {console.log('收到主线程消息:', e.data);postMessage('Worker已收到消息');
};
线程间通信
主线程发送消息:
worker.postMessage({ type: 'start', data: 42 });Worker线程接收消息:
// worker.js
self.onmessage = function(e) {if (e.data.type === 'start') {const result = heavyCalculation(e.data.data);postMessage({ result });
};
高级特性
错误处理
worker.onerror = function(error) {console.error('Worker错误:', error);
};
终止 Worker
// 主线程
worker.terminate();
// Worker线程
self.close();
使用 ES Modules
// 主线程
const worker = new Worker('worker.js', { type: 'module' });
// worker.js
import { heavyTask } from './utils.js';self.onmessage = async (e) => {const result = await heavyTask(e.data);postMessage(result);
};
实际应用场景
图像处理
// 主线程
const imageWorker = new Worker('image-processor.js');
imageWorker.postMessage({ imageData });// image-processor.js
self.onmessage = function(e) {const processed = applyFilters(e.data.imageData);postMessage(processed);
};
大数据处理
// 主线程
const dataWorker = new Worker('data-processor.js');
dataWorker.postMessage(largeDataset);dataWorker.onmessage = function(e) {updateUI(e.data.results);
};
轮询任务
// worker.js
function poll() {fetch('/api/status').then(res => res.json()).then(data => {postMessage(data);setTimeout(poll, 5000);});
self.onmessage = function(e) {if (e.data === 'start') poll();
};
性能优化技巧
批量传输数据:
// 使用Transferable对象提高性能const buffer = new ArrayBuffer(32);worker.postMessage(buffer, [buffer]);
Worker复用:
// 创建可复用的Worker池class WorkerPool {constructor(size, workerScript) {this.pool = Array(size).fill().map(() => new Worker(workerScript));
}
懒加载Worker:
let worker;function getWorker() {if (!worker) {worker = new Worker('worker.js');
return worker;
现代开发方式
使用 worker-loader (Webpack)
// webpack.config.js
module.exports = {module: {rules: [
test: /\.worker\.js$/,use: { loader: 'worker-loader' }
]};
// 使用
import Worker from './my.worker.js';
const worker = new Worker();
Vite中的Worker使用
// 直接导入为Worker
import Worker from './worker.js?worker';const worker = new Worker();
Comlink 简化通信
// 主线程
import * as Comlink from 'comlink';
const worker = new Worker('worker.js');
const api = Comlink.wrap(worker);
// worker.js
import * as Comlink from 'comlink';
const api = {async heavyTask(param) {// 长时间任务
};Comlink.expose(api);
限制与注意事项
DOM限制:
-
Worker无法直接访问DOM
-
不能使用window、document等对象
通信限制:
-
传递的数据会被复制(结构化克隆算法)
-
无法传递函数、DOM元素等
同源策略:
Worker脚本必须与主线程同源
调试技巧:
Chrome开发者工具 → Sources → Worker调试
使用console.log调试Worker
最佳实践
合理使用Transferable:
// 传递大型二进制数据const canvas = document.querySelector('canvas');const offscreen = canvas.transferControlToOffscreen();worker.postMessage({ canvas: offscreen }, [offscreen]);
错误恢复机制:
worker.onerror = function() {// 重启Worker或降级处理initializeWorker();};
优雅终止:
function terminateWorker(worker) {worker.postMessage('terminate');setTimeout(() => {if (worker) worker.terminate();}, 1000);
版本控制:
// Worker文件名加入版本号const worker = new Worker(`worker.v2.js?${CACHE_BUST}`);
Web Workers为CPU密集型任务提供了完美的解决方案,合理使用可以显著提升Web应用的性能和用户体验。