Browser Support
Chrome 4+ · Firefox 41+ · Safari 10+ · Edge 12+ MessageChannel is available in main thread, Worker, and ServiceWorker.
Overview
MessageChannel lets you establish a private, direct communication channel between two contexts without going through Worker's main script.
Typical scenario: main thread manages two Workers, but these two Workers need to directly exchange large amounts of data. If routing through main thread, all data must "enter main thread, exit main thread", with one extra copy overhead. With MessageChannel, two Workers can talk directly, main thread only establishes the connection.
Quick Start
js
// === main.js ===
const channel = new MessageChannel();
const port1 = channel.port1;
const port2 = channel.port2;
const workerB = new Worker('./worker-b.js');
workerB.postMessage({ type: 'PORT', port: port2 }, [port2]);
port1.onmessage = (e) => console.log('A says:', e.data);
port1.start();1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Two Ports of MessageChannel
new MessageChannel() returns { port1, port2 }:
port1sends →port2receivesport2sends →port1receives- When one end closes, the other gets
onmessageerror
Comparison with BroadcastChannel
| Feature | MessageChannel | BroadcastChannel |
|---|---|---|
| Communication target | Two specific ports | All same-origin tabs + Workers |
| Needs relay | Ports must be manually distributed | No, naturally broadcasts |
| Direction | Full-duplex, direct | Full-duplex, broadcast |
| Compatibility | Better (IE10+) | Safari 15.4+ |
Notes
- Ports must
.start(): Even ifonmessageis bound, some browsers require explicit.start()to activate port - Don't bind both
onmessageandaddEventListener('message')on same port: Messages will be processed twice - Port transfer removes ownership from original thread: If
postMessagetransfersport2as a transferable, original thread can no longer use it