messagechannel 可实现两个 worker 间点对点直接通信,主线程创建通道并转移 port 给各 worker,worker 调用 port.start() 后即可双向收发消息,无需主线程中转。

MessageChannel 可以让两个 Worker 之间建立**点对点的直接通信通道**,绕过主线程中转,降低延迟、提升效率。关键在于:主线程创建 MessageChannel 实例,把它的两个 port 分别传递给两个 Worker,之后它们就能通过各自的 port 直接收发消息。
1. 创建 MessageChannel 并分发端口
主线程负责初始化通道,并用 postMessage(..., [port]) 将每个 port 转移给对应 Worker(注意必须传入 transfer list):
// main.js
const channel = new MessageChannel();
const workerA = new Worker('worker-a.js');
const workerB = new Worker('worker-b.js');
// 把 channel.port1 给 workerA,port2 给 workerB
workerA.postMessage({ type: 'init', port: channel.port1 }, [channel.port1]);
workerB.postMessage({ type: 'init', port: channel.port2 }, [channel.port2]);
2. Worker 中接收并启用端口
每个 Worker 收到 port 后需调用 port.start()(或监听 message 事件自动启动),之后即可用 port.postMessage() 发送、port.onmessage 接收:
// worker-a.js
let remotePort;
self.onmessage = function(e) {
if (e.data.type === 'init') {
remotePort = e.data.port;
remotePort.start(); // 启动端口(启用 message 事件)
// 示例:向 workerB 发消息
remotePort.postMessage({ from: 'workerA', text: 'Hello from A!' });
}
};
// 接收来自 workerB 的消息
remotePort.onmessage = function(e) {
console.log('Received in A:', e.data);
};
// worker-b.js(结构类似)
let remotePort;
self.onmessage = function(e) {
if (e.data.type === 'init') {
remotePort = e.data.port;
remotePort.start();
remotePort.postMessage({ from: 'workerB', text: 'Hi from B!' });
}
};
remotePort.onmessage = function(e) {
console.log('Received in B:', e.data);
};
3. 注意事项与最佳实践
- 端口只能被一个线程持有:transfer 后原主线程的 port 即失效,不可再用;
-
必须显式 start():若未调用
start(),又未设置onmessage,消息会被丢弃; - 支持结构化克隆:可传对象、数组、ArrayBuffer 等(不支持函数、DOM 节点);
-
可关闭端口:任一端调用
port.close(),另一端会触发onmessageerror或收到终止信号; - 无需主线程参与通信:一旦端口分发完成,两个 Worker 完全独立双向通信,主线程零负担。
4. 验证通信是否成功
可在两个 Worker 中互相发送带唯一标识的消息(如时间戳 + ID),并在对方回调中打印确认。若能看到成对日志(A 发 → B 收,B 发 → A 收),说明通道已连通。调试时注意浏览器开发者工具的 “Application > Service Workers” 或 “Console” 中查看各 Worker 的输出。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











