如何用 postMessage 与 onmessage 在主线程与线程间通信的重点在于把前置条件、操作顺序和容易误判的地方分清楚。
主线程与Web Worker通过postMessage和onmessage实现双向异步通信,支持结构化克隆数据及transferList零拷贝传输;Worker可用addEventListener避免监听器覆盖;MessageChannel可实现多端隔离通信。
主线程与 Web Worker 之间通过 postMessage 和 onmessage 实现双向通信,核心是“发送消息”和“监听消息”两个动作,且双方都需主动参与。
在主线程中创建 Worker 实例后,调用其 postMessage() 方法即可发送数据:
transferList,用于零拷贝传输 ArrayBuffer 或 MessagePort,提升大数组性能const worker = new Worker('worker.js');worker.postMessage({ type: 'START', data: [1, 2, 3] });// 或传输 ArrayBuffer(原数组将被清空)const buffer = new ArrayBuffer(1024);worker.postMessage(buffer, [buffer]);
在 worker.js 中,通过全局的 onmessage 属性或 addEventListener('message', ...) 监听主线程发来的消息:
event.data 是主线程发送的数据副本(结构化克隆)postMessage() 回复主线程,同样支持 transferList
onmessage 多次,否则会覆盖前一个监听器;推荐用 addEventListener 更安全self.onmessage = function(e) { const { type, data } = e.data; if (type === 'START') { const result = data.map(x => x * 2); self.postMessage({ type: 'RESULT', data: result }); }};
主线程需为 Worker 实例设置 onmessage 或添加事件监听器来接收 Worker 的回复:
worker.onmessage 是最常用方式,e.data 即 Worker 发来的数据worker.addEventListener('message', ...)
worker.onerror 或使用 try/catch 包裹 Worker 内部逻辑worker.onmessage = function(e) { console.log('Worker 返回:', e.data); // { type: 'RESULT', data: [2, 4, 6] }};<p>worker.onerror = function(e) {console.error('Worker 执行出错:', e.message);};
当需要主线程与多个 Worker 之间隔离通信,或 Worker 之间直连,可借助 MessageChannel:
MessagePort 对象,各自持有独立通道的一端worker.postMessage(..., [port]),Worker 收到后调用 port.start() 并监听 port.onmessage
onmessage 上,实现点对点、解耦通信