Start · Sprachen · JavaScript · Referenz · MessageEvent.ports

MessageEvent.ports

Eigenschaft

Schreibgeschützte Eigenschaft, die ein eingefrorenes Array der mit der Nachricht übertragenen <code>MessagePort</code>-Objekte liefert.

seit JavaScript Baseline: alle modernen Browser Kategorie: webapi

Signatur

MessageEvent.ports

Beschreibung

Die Eigenschaft ports eines MessageEvent enthält alle MessagePort-Objekte, die der Absender beim Aufruf von postMessage() im Transfer-Argument mitgeschickt hat. So kann der Empfänger einen eigenen, direkten Kommunikationskanal zum Absender (oder zu einem Dritten) übernehmen.

Typischer Einsatz ist das Muster mit MessageChannel: Eine Seite erzeugt einen Kanal, behält port1 und übergibt port2 per postMessage() an ein iframe, einen Worker oder einen Service Worker. Der Empfänger liest den Port über event.ports[0] aus und nutzt ihn für eine exklusive Zwei-Wege-Kommunikation – etwa für Anfrage-Antwort-Muster, ohne globale message-Listener zu belasten.

Das Array ist eingefroren (Object.isFrozen(event.ports) === true) und bei Nachrichten ohne übertragene Ports leer. Übertragene Ports sind beim Absender danach unbrauchbar (neutralisiert), da ihr Besitz an den Empfänger übergeht.

Rückgabewert

Typ
ReadonlyArray<MessagePort>
Beschreibung
Eingefrorenes Array der übertragenen MessagePort-Objekte; leeres Array, wenn keine Ports mitgeschickt wurden.

Beispiele

Port an ein iframe übergeben und empfangen

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

channel.port1.onmessage = (e) => console.log('Antwort aus iframe:', e.data);

iframe.addEventListener('load', () => {
  // port2 wird übertragen (drittes Argument = Transfer-Liste)
  iframe.contentWindow.postMessage('init', 'https://child.example', [channel.port2]);
});

// Im iframe (https://child.example)
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://parent.example') return;
  const [port] = event.ports;
  if (!port) return;
  port.onmessage = (e) => port.postMessage(`Echo: ${e.data}`);
  port.postMessage('Kanal steht');
});
Antwort aus iframe: Kanal steht

Anfrage-Antwort mit einem Worker über einen eigenen Kanal

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

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

const result = await ask({ op: 'sum', values: [1, 2, 3] });
console.log(result);

// worker.js
self.onmessage = (event) => {
  const { op, values } = event.data;
  const [replyPort] = event.ports;
  if (op === 'sum') replyPort.postMessage(values.reduce((a, b) => a + b, 0));
};
6

Eigenschaften des ports-Arrays prüfen

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

window.addEventListener('message', (event) => {
  console.log(event.ports.length);
  console.log(Object.isFrozen(event.ports));
  console.log(event.ports[0] instanceof MessagePort);
}, { once: true });

window.postMessage('test', '*', [port2]);
1 true true

// Wichtig · Fallstricke

  • Transfer-Liste nötig: Ports erscheinen nur in event.ports, wenn sie im Transfer-Argument von postMessage() (bzw. { transfer: [...] }) übergeben werden. Stecken sie nur in data, ohne übertragen zu werden, wirft der Aufruf einen DataCloneError.
  • Eingefroren: Das Array kann nicht verändert werden; push() o. Ä. schlägt fehl (im Strict Mode mit TypeError).
  • Neutralisierung: Nach der Übertragung ist der Port beim Absender nicht mehr verwendbar.
  • start() bei addEventListener: Wer auf dem empfangenen Port addEventListener('message', …) statt onmessage nutzt, muss port.start() aufrufen, sonst kommen keine Nachrichten an.
  • Sicherheit: Bei Cross-Origin-Nachrichten immer event.origin prüfen, bevor ein empfangener Port genutzt wird – sonst kann eine fremde Seite einen Kanal einschleusen.
  • Bei message-Events von WebSocket oder EventSource ist ports stets leer.
  • Kompatibilität: in allen modernen Browsern sowie in Web-, Shared- und Service-Workern verfügbar.