worker与主线程通过postmessage通信,本质是结构化克隆+异步事件驱动,不共享内存;数据被克隆副本传输,修改不影响原对象;支持transferable objects实现arraybuffer零拷贝。

Worker线程与主线程通过 postMessage 通信,本质是**结构化克隆 + 异步事件驱动**,不共享内存,也不直接访问对方作用域。
通信基础:单向异步、数据拷贝而非引用
主线程和 Worker 各自拥有独立的全局执行环境(Window 或 WorkerGlobalScope),无法直接读写对方变量。调用 postMessage(data) 时:
- 浏览器对
data执行**结构化克隆算法(Structured Clone Algorithm)**:支持对象、数组、Date、RegExp、Blob、File、ArrayBuffer、TypedArray 等,但不支持函数、DOM 节点、undefined、Symbol 或循环引用; - 克隆后的数据被序列化并跨线程传输,原对象在发送方保持不变;
- 接收方在
message事件中拿到的是全新副本,修改它不会影响发送方; - 整个过程异步,无阻塞,也不保证顺序(但在同一线程内多个
postMessage调用通常按序触发事件)。
主线程启动 Worker 并监听消息
主线程使用 new Worker('path/to/worker.js') 创建实例后,需显式绑定 message 事件监听器:
const worker = new Worker('calc.js');
worker.postMessage({ type: 'start', data: [1, 2, 3, 4] });
worker.onmessage = function(e) {
console.log('收到 Worker 返回:', e.data); // e.data 是克隆副本
};
// 或用 addEventListener
worker.addEventListener('message', e => {
if (e.data.type === 'result') {
document.getElementById('output').textContent = e.data.value;
}
});
Worker 内部收发消息的写法
Worker 全局作用域中,this 指向 self(即 WorkerGlobalScope),可直接调用 postMessage 向主线程发消息,并监听 message 事件:
// calc.js
self.onmessage = function(e) {
const { type, data } = e.data;
if (type === 'start') {
const sum = data.reduce((a, b) => a + b, 0);
// 发送结果回主线程
self.postMessage({ type: 'result', value: sum });
}
};
注意:self.postMessage 和 postMessage 在 Worker 中等价,但推荐显式写 self.postMessage 提高可读性。
进阶:传输 ArrayBuffer 避免拷贝开销
对于大块二进制数据(如图像处理、音频解码),结构化克隆会完整复制 ArrayBuffer,造成性能浪费。此时可用 Transferable Objects 技术,把 ArrayBuffer 的所有权移交给对方线程,实现零拷贝:
- 主线程发送时传入第二个参数:
worker.postMessage(arrayBuffer, [arrayBuffer]); - Worker 接收后,该 ArrayBuffer 在主线程中自动变为
detached(不可再访问); - Worker 可直接操作该缓冲区,处理完后也可用同样方式传回(如传回视图或新 ArrayBuffer);
- 仅支持
ArrayBuffer、MessagePort、ImageBitmap等少数类型,且只能转移一次。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










