Start · Sprachen · JavaScript · Referenz · ExtendableMessageEvent.ports

ExtendableMessageEvent.ports

Eigenschaft

Schreibgeschütztes, eingefrorenes Array der <code>MessagePort</code>-Objekte, die mit einer Nachricht an einen Service Worker übertragen wurden.

seit JavaScript Baseline: alle modernen Browser (Service Worker) Kategorie: webapi

Signatur

ExtendableMessageEvent.ports

Beschreibung

Die Eigenschaft ports des ExtendableMessageEvent enthält alle MessagePort-Objekte, die der Absender beim Aufruf von postMessage() im Transfer-Array mitgeschickt hat. Meist ist das der Port port2 eines MessageChannel, den die Seite erzeugt hat, damit der Service Worker direkt und gezielt antworten kann.

Das ist das übliche Muster für eine Anfrage-Antwort-Kommunikation zwischen Seite und Service Worker: Die Seite behält port1 und wartet dort auf die Antwort, der Service Worker schreibt über event.ports[0].postMessage() zurück. So muss man Antworten nicht über alle Clients verteilen und keine eigenen Kennungen verwalten, um sie zuzuordnen.

Wurden keine Ports übertragen, ist ports ein leeres Array. Das Array ist eingefroren (frozen) und lässt sich nicht verändern. Die Ports selbst können Sie aber ganz normal verwenden, also Nachrichten senden, auf Nachrichten hören und sie schließen.

Rückgabewert

Typ
ReadonlyArray<MessagePort>
Beschreibung
Eingefrorenes Array mit den übertragenen MessagePort-Objekten. Wurden keine Ports mitgeschickt, ist es leer.

Beispiele

Seite: MessageChannel an den Service Worker schicken

// main.js
const askServiceWorker = async (payload) => {
  const registration = await navigator.serviceWorker.ready;
  return new Promise((resolve, reject) => {
    const channel = new MessageChannel();
    channel.port1.onmessage = (event) => {
      channel.port1.close();
      event.data.error ? reject(event.data.error) : resolve(event.data);
    };
    // port2 wird übertragen und landet in event.ports im Service Worker
    registration.active.postMessage(payload, [channel.port2]);
  });
};

const result = await askServiceWorker({ type: 'CACHE_SIZE' });
console.log(result);
{ entries: 42 }

Service Worker: über event.ports[0] antworten

// sw.js
self.addEventListener('message', (event) => {
  const [replyPort] = event.ports;
  if (!replyPort) return; // kein Antwortkanal mitgeschickt

  if (event.data?.type === 'CACHE_SIZE') {
    // waitUntil hält den Service Worker aktiv, bis die Antwort raus ist
    event.waitUntil((async () => {
      const cache = await caches.open('v1');
      const keys = await cache.keys();
      replyPort.postMessage({ entries: keys.length });
    })());
  } else {
    replyPort.postMessage({ error: 'Unbekannter Typ' });
  }
});

Prüfen, wie viele Ports angekommen sind

// sw.js
self.addEventListener('message', (event) => {
  console.log('Anzahl Ports:', event.ports.length);
  console.log('Eingefroren:', Object.isFrozen(event.ports));
});
Anzahl Ports: 1 Eingefroren: true

// Wichtig · Fallstricke

  • Ports kommen nur an, wenn sie im Transfer-Array (zweites Argument von postMessage()) stehen. Stecken sie nur im Nachrichtenobjekt, wirft der Aufruf einen DataCloneError.
  • Ein übertragener Port ist beim Absender danach unbrauchbar (neutered). Die Seite muss port1 behalten und port2 übertragen.
  • Asynchrone Arbeit vor der Antwort gehört in event.waitUntil(). Sonst kann der Browser den Service Worker beenden, bevor die Antwort gesendet ist.
  • Das Array ist eingefroren: push() oder Zuweisungen werfen im Strict Mode einen TypeError.
  • Wenn Sie onmessage setzen, wird der Port automatisch gestartet. Mit addEventListener('message', …) müssen Sie dagegen port.start() selbst aufrufen.
  • Schließen Sie nicht mehr benötigte Ports mit close(), damit keine Speicherlecks entstehen.
  • Nur im Service-Worker-Kontext verfügbar, der einen sicheren Ursprung (HTTPS oder localhost) voraussetzt.