Web Worker 和主线程之间的通信主要通过 postMessage() 方法和 onmessage 事件实现。
基本通信机制
主线程向 Worker 发送消息
javascriptconst worker = new Worker('worker.js'); // 发送简单数据 worker.postMessage('Hello Worker'); // 发送复杂对象 worker.postMessage({ type: 'compute', data: [1, 2, 3, 4, 5] }); // 发送可转移对象(Transferable Objects) const buffer = new ArrayBuffer(1024); worker.postMessage({ buffer }, [buffer]);
Worker 向主线程发送消息
javascript// worker.js self.onmessage = function(event) { const result = processData(event.data); self.postMessage(result); }; // 或者使用 addEventListener self.addEventListener('message', function(event) { self.postMessage({ status: 'received' }); });
消息传递特点
1. 深拷贝 vs 转移
默认情况下,消息通过深拷贝传递:
javascript// 深拷贝 - 原数据保留 const data = { value: 42 }; worker.postMessage(data); console.log(data.value); // 42 - 数据仍然存在
使用Transferable Objects进行转移:
javascript// 转移 - 原数据被清空 const buffer = new ArrayBuffer(1024); worker.postMessage({ buffer }, [buffer]); console.log(buffer.byteLength); // 0 - 数据已被转移
2. 结构化克隆算法
postMessage 使用结构化克隆算法,支持:
- 基本类型(string, number, boolean, null, undefined)
- 对象和数组
- Date, RegExp, Blob, File, ArrayBuffer
- Map, Set, ImageData
不支持:
- 函数
- DOM 节点
- Error 对象
- Symbol
双向通信示例
javascript// 主线程 const worker = new Worker('worker.js'); worker.onmessage = function(event) { console.log('Worker says:', event.data); }; worker.postMessage({ action: 'start' }); // worker.js self.onmessage = function(event) { if (event.data.action === 'start') { // 执行任务 const result = heavyComputation(); self.postMessage({ action: 'complete', result }); } };
消息队列
消息是异步的,通过消息队列传递:
javascript// 主线程连续发送多条消息 for (let i = 0; i < 5; i++) { worker.postMessage({ index: i }); } // Worker 按顺序接收 self.onmessage = function(event) { console.log('Processing:', event.data.index); };
错误处理
javascript// 主线程监听 Worker 错误 worker.onerror = function(event) { console.error('Worker error:', event.message); console.error('Filename:', event.filename); console.error('Line:', event.lineno); }; // Worker 内部错误处理 try { // 可能出错的代码 } catch (error) { self.postMessage({ error: error.message }); }
性能优化建议
- 使用 Transferable Objects:对于大数据(ArrayBuffer、Blob),使用转移而非拷贝
- 批量处理:减少消息传递次数,合并数据
- 避免频繁通信:尽量在 Worker 内部完成更多计算
- 使用 SharedArrayBuffer:多个 Worker 共享内存(需要特定头部配置)