Signatur
Beschreibung
Ein MessagePort ist ein Ende eines MessageChannel bzw. der Kommunikationskanal eines SharedWorker. Eingehende Nachrichten landen zunächst in einer Port-Nachrichtenwarteschlange, die anfangs deaktiviert ist. Erst mit start() wird die Warteschlange freigegeben und die Nachrichten werden als message-Ereignisse zugestellt.
Wichtig ist der Unterschied zwischen den beiden Wegen, einen Empfänger zu registrieren:
- Wird die Eigenschaft
port.onmessagegesetzt, ruft der Browserstart()implizit auf. - Wird dagegen
port.addEventListener("message", handler)verwendet, mussstart()explizit aufgerufen werden – sonst kommen keine Nachrichten an.
Das verzögerte Starten ist bewusst so entworfen: Man kann erst sämtliche Listener registrieren und die Zustellung dann gezielt anstoßen, ohne dass Nachrichten zwischenzeitlich verloren gehen. Bis zum Aufruf werden Nachrichten gepuffert, nicht verworfen.
Beispiele
MessageChannel mit addEventListener – start() ist Pflicht
const { port1, port2 } = new MessageChannel();
port2.addEventListener('message', (event) => {
console.log('Empfangen:', event.data);
});
// Ohne diesen Aufruf würde der Listener nie ausgelöst
port2.start();
port1.postMessage({ typ: 'gruss', text: 'Hallo Port!' });
onmessage startet den Port implizit
const { port1, port2 } = new MessageChannel();
// Setzen von onmessage ruft start() automatisch auf
port2.onmessage = (event) => console.log('Antwort:', event.data);
port1.postMessage(42);
SharedWorker: Port im Worker starten
// shared-worker.js
const verbindungen = new Set();
self.addEventListener('connect', (event) => {
const port = event.ports[0];
verbindungen.add(port);
port.addEventListener('message', (e) => {
// Nachricht an alle verbundenen Tabs weiterreichen
for (const p of verbindungen) p.postMessage(e.data);
});
port.start(); // nötig wegen addEventListener
});
// main.js
const worker = new SharedWorker('shared-worker.js');
worker.port.addEventListener('message', (e) => console.log('Broadcast:', e.data));
worker.port.start();
worker.port.postMessage('Neuer Tab ist online');
Erst Listener sammeln, dann gezielt starten
const { port1, port2 } = new MessageChannel();
// Nachrichten werden gesendet, bevor jemand zuhört – sie werden gepuffert
port1.postMessage('erste');
port1.postMessage('zweite');
const empfangen = [];
port2.addEventListener('message', (e) => empfangen.push(e.data));
setTimeout(() => {
port2.start(); // jetzt werden beide gepufferten Nachrichten zugestellt
setTimeout(() => console.log(empfangen), 0);
}, 100);
// Wichtig · Fallstricke
- Häufigster Fehler:
addEventListener("message", …)ohne anschließendesstart()– es erscheint keine Fehlermeldung, die Nachrichten kommen einfach nicht an. - Mehrfaches Aufrufen von
start()ist unschädlich; bereits gestartete Ports bleiben unverändert. - Der
porteines dediziertenWorkerbzw.selfim Worker benötigt keinstart(); das betrifft nur echteMessagePort-Objekte (MessageChannel, SharedWorker,event.ports). - Nach
close()hatstart()keine Wirkung mehr. - In Node.js (
worker_threads) verhält sichMessagePortähnlich:port.on('message')startet den Port automatisch, beiaddEventListeneriststart()nötig. - Kompatibilität: in allen modernen Browsern unterstützt;
SharedWorkerist jedoch in manchen mobilen Browsern (z. B. älteres Chrome für Android) nicht verfügbar.