Start · Sprachen · JavaScript · Referenz · MessageChannel.port2

MessageChannel.port2

Eigenschaft

Schreibgeschützte Eigenschaft, die den zweiten <code>MessagePort</code> eines <code>MessageChannel</code> liefert. Meist wird er an einen anderen Kontext übertragen.

seit JavaScript Baseline: alle Browser (seit 2015); Node.js 15+ gl Kategorie: webapi

Signatur

MessageChannel.port2

Beschreibung

Ein MessageChannel besteht aus zwei miteinander verbundenen MessagePort-Objekten: port1 und port2. Was an einem Port mit postMessage() gesendet wird, kommt am anderen Port als message-Ereignis an. port2 liefert den zweiten dieser beiden Ports.

Üblicherweise bleibt port1 im aktuellen Kontext. port2 wird als übertragbares Objekt (Transferable) an einen anderen Kontext geschickt, etwa ein <iframe>, einen Web Worker oder einen Service Worker. Dazu übergibt man es im Transfer-Array von postMessage(). So entsteht ein privater, direkter Kommunikationskanal zwischen zwei Kontexten, unabhängig vom globalen message-Kanal von window.

Die Eigenschaft ist schreibgeschützt und gibt bei jedem Zugriff dasselbe MessagePort-Objekt zurück. Nach der Übertragung an einen anderen Kontext ist der Port im Ursprungskontext neutralisiert: Er lässt sich dort nicht mehr sinnvoll verwenden.

Rückgabewert

Typ
MessagePort
Beschreibung
Der zweite Port des Kanals. Er ist mit port1 verbunden und wird typischerweise an einen anderen Kontext übertragen.

Beispiele

Port an ein iframe übertragen

const channel = new MessageChannel();
const iframe = document.querySelector('iframe');

// Antworten aus dem iframe über port1 empfangen
channel.port1.onmessage = (event) => {
  console.log('Antwort aus iframe:', event.data);
};

iframe.addEventListener('load', () => {
  // port2 im Transfer-Array übergeben – nicht nur als Daten!
  iframe.contentWindow.postMessage('init', 'https://widget.example.com', [channel.port2]);
});

// Im iframe (widget.example.com):
// window.addEventListener('message', (event) => {
//   if (event.origin !== 'https://parent.example.com') return;
//   const [port] = event.ports;
//   port.postMessage('Hallo vom Widget');
// });
Antwort aus iframe: Hallo vom Widget

Anfrage/Antwort mit einem Web Worker

// main.js
const worker = new Worker('worker.js');

const askWorker = (payload) => new Promise((resolve) => {
  const { port1, port2 } = new MessageChannel();
  port1.onmessage = (event) => {
    resolve(event.data);
    port1.close();
  };
  worker.postMessage(payload, [port2]);
});

const result = await askWorker({ a: 2, b: 3 });
console.log('Summe:', result);

// worker.js
// self.onmessage = ({ data, ports }) => {
//   ports[0].postMessage(data.a + data.b);
// };
Summe: 5

Beide Ports lokal verbinden (z. B. für Tests)

const { port1, port2 } = new MessageChannel();

port2.addEventListener('message', (event) => {
  console.log('port2 empfängt:', event.data);
});
// Bei addEventListener muss start() explizit aufgerufen werden
port2.start();

port1.postMessage({ typ: 'ping' });
console.log(port2 instanceof MessagePort);
true port2 empfängt: { typ: 'ping' }

// Wichtig · Fallstricke

  • Nur per Transfer-Liste übertragen: Legt man port2 nur in die Nachrichtendaten statt ins Transfer-Array (drittes Argument von window.postMessage() bzw. zweites von Worker.postMessage()), wird ein DataCloneError ausgelöst.
  • Neutralisierung: Nach der Übertragung ist port2 im Ursprungskontext unbrauchbar. Dort gesendete Nachrichten gehen verloren.
  • start() nicht vergessen: Wer addEventListener('message', …) statt onmessage nutzt, muss port.start() aufrufen. Sonst kommen keine Nachrichten an.
  • Sicherheit: Beim Übertragen an ein iframe immer einen konkreten targetOrigin angeben, nicht '*'. Sonst kann ein fremdes Dokument den Port abgreifen. Auf der Empfängerseite event.origin prüfen, bevor man event.ports verwendet.
  • Speicher: Nicht mehr benötigte Ports mit close() schließen, damit keine Ressourcen offen bleiben.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. In Node.js ist MessageChannel ab Version 15 global verfügbar, davor über require('worker_threads').