Worker 的基本概念
Web Worker 是浏览器提供的在后台线程执行脚本的能力。每个 Worker 有自己的:
- 事件循环:独立于主线程
- 全局作用域:不是 window,是 DedicatedWorkerGlobalScope
- 消息队列:接收来自主线程的消息
主线程和 Worker 通过 postMessage 异步通信。
Worker 的创建和通信
// 主线程
const worker = new Worker('compute.js');
worker.postMessage({ type: 'start', data: 1000000 });
worker.onmessage = function(e) {
console.log('Worker result:', e.data);
};
worker.onerror = function(err) {
console.error('Worker error:', err);
};
// compute.js (Worker 脚本)
self.onmessage = function(e) {
if (e.data.type === 'start') {
const result = heavyComputation(e.data.data);
self.postMessage(result);
}
};
function heavyComputation(n) {
// 耗时计算
return n * 2;
}
数据的传递方式
复制传递(Structured Clone)
默认情况下,postMessage 的数据会被复制到 Worker:
// 主线程
const data = { large: new Array(1e6) };
worker.postMessage(data); // 数据被复制
Transferable 对象(转移)
大数据可以用转移模式,避免复制开销:
const buffer = new ArrayBuffer(8 * 1024 * 1024);
worker.postMessage(buffer, [buffer]); // buffer 被转移,主线程无法再访问
Worker 的事件循环
Worker 有自己独立的事件循环,不阻塞主线程:
// Worker 中也可以使用 setTimeout, setInterval
self.setInterval(() => {
self.postMessage('heartbeat');
}, 1000);
// Worker 中也可以使用 Promise
Promise.resolve().then(() => console.log('microtask in worker'));
常见应用场景
图像处理
// Worker 处理图片滤镜
self.onmessage = function(e) {
const imageData = e.data;
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
// 灰度滤镜
const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
data[i] = data[i + 1] = data[i + 2] = avg;
}
self.postMessage(imageData);
};
加密解密
// Worker 处理加密
async function encryptWithWorker(data, key) {
const worker = new Worker('crypto.js');
return new Promise((resolve, reject) => {
worker.onmessage = (e) => resolve(e.data);
worker.onerror = (e) => reject(e.error);
worker.postMessage({ data, key });
});
}
Worker 的生命周期
- 创建:通过
new Worker()创建 - 运行:Worker 脚本开始执行
- 终止:通过
worker.terminate()或 Worker 内部self.close()终止
// 主动终止 Worker
worker.terminate();
这一章想说的
Web Worker 提供了在后台线程执行 JavaScript 的能力,实现了真正的多线程并行。
关键点:
- Worker 有独立的事件循环,不阻塞主线程
- 主线程和 Worker 通过 postMessage 异步通信
- 数据默认是复制传递,大数据可用 Transferable 转移
Worker 是处理 CPU 密集型任务的正确方式,而不是用 setTimeout 分割任务。