乐闻世界logo
搜索文章和话题

Web Worker 和主线程之间如何进行通信?

2月21日 15:12

Web Worker 和主线程之间的通信主要通过 postMessage() 方法和 onmessage 事件实现。

基本通信机制

主线程向 Worker 发送消息

javascript
const 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 }); }

性能优化建议

  1. 使用 Transferable Objects:对于大数据(ArrayBuffer、Blob),使用转移而非拷贝
  2. 批量处理:减少消息传递次数,合并数据
  3. 避免频繁通信:尽量在 Worker 内部完成更多计算
  4. 使用 SharedArrayBuffer:多个 Worker 共享内存(需要特定头部配置)
标签:Web Worker