Start · Sprachen · JavaScript · Referenz · ExtendableMessageEvent

ExtendableMessageEvent

Schnittstelle

Ereignisobjekt des <code>message</code>-Ereignisses im Service Worker. Es enthält Daten, Absender und Ports und verlängert mit <code>waitUntil()</code> die Lebensdauer des Workers.

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

Signatur

interface ExtendableMessageEvent extends ExtendableEvent

Beschreibung

ExtendableMessageEvent ist das Ereignisobjekt, das ein Service Worker erhält, wenn eine Seite (ein Client) ihm eine Nachricht schickt, z. B. mit navigator.serviceWorker.controller.postMessage() oder registration.active.postMessage(). Das Ereignis wird auf dem ServiceWorkerGlobalScope ausgelöst. Man empfängt es mit self.addEventListener("message", handler) oder über self.onmessage.

Es erbt von ExtendableEvent, nicht von MessageEvent. Deshalb steht die Methode waitUntil() zur Verfügung: Damit teilt man dem Browser mit, dass der Worker aktiv bleiben muss, bis ein Promise erfüllt ist, etwa bis ein Cache aktualisiert ist oder eine Antwort an alle Clients verschickt wurde. Ohne waitUntil() kann der Browser den Worker direkt nach dem synchronen Handler beenden.

Wichtige Eigenschaften (alle schreibgeschützt):

  • data: die übermittelten Daten, eine per structured clone erzeugte Kopie.
  • source: der Absender, ein Client, ServiceWorker oder MessagePort. Damit kann man gezielt antworten.
  • origin: der Ursprung (Origin) des Absenders.
  • lastEventId: bei Service-Worker-Nachrichten meist ein leerer String.
  • ports: ein Array der übertragenen MessagePort-Objekte, z. B. für eine Antwort über einen MessageChannel.

Typische Einsatzfälle sind Befehle von der Seite an den Worker (z. B. "SKIP_WAITING", Cache leeren, Dateien vorab laden) und Anfrage-Antwort-Muster über einen MessageChannel.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Name des Ereignisses, in der Regel "message" (nur beim Konstruktor new ExtendableMessageEvent(type, init)).
$init object {} Optionales Objekt mit den Feldern data, origin, lastEventId, source (Client|ServiceWorker|MessagePort|null) und ports (MessagePort[]) sowie bubbles, cancelable und composed.

Rückgabewert

Typ
ExtendableMessageEvent
Beschreibung
Ein neues Ereignisobjekt, wenn es mit dem Konstruktor erzeugt wird. Diesen braucht man hauptsächlich für Tests im Service-Worker-Kontext.

Beispiele

Nachricht im Service Worker empfangen und dem Absender antworten

// sw.js
self.addEventListener("message", (event) => {
  console.log("Von:", event.origin, "Daten:", event.data);

  // Worker aktiv halten, bis die Antwort verschickt ist
  event.waitUntil(
    (async () => {
      if (event.source) {
        event.source.postMessage({ type: "PONG", received: event.data });
      }
    })()
  );
});

// Seite (main.js)
navigator.serviceWorker.addEventListener("message", (e) => {
  console.log("Antwort:", e.data);
});
const reg = await navigator.serviceWorker.ready;
reg.active.postMessage({ type: "PING" });
Antwort: { type: "PONG", received: { type: "PING" } }

SKIP_WAITING-Befehl für ein Update des Service Workers

// sw.js
self.onmessage = (event) => {
  if (event.data?.type === "SKIP_WAITING") {
    event.waitUntil(self.skipWaiting());
  }
};

// Seite: wartenden Worker aktivieren
const reg = await navigator.serviceWorker.getRegistration();
reg?.waiting?.postMessage({ type: "SKIP_WAITING" });

Anfrage/Antwort über MessageChannel (event.ports)

// sw.js
self.addEventListener("message", (event) => {
  if (event.data?.type !== "CACHE_SIZE") return;
  const [port] = event.ports;
  event.waitUntil(
    (async () => {
      const cache = await caches.open("v1");
      const keys = await cache.keys();
      port.postMessage({ size: keys.length });
    })()
  );
});

// Seite
const askCacheSize = () =>
  new Promise((resolve) => {
    const { port1, port2 } = new MessageChannel();
    port1.onmessage = (e) => resolve(e.data.size);
    navigator.serviceWorker.controller.postMessage(
      { type: "CACHE_SIZE" },
      [port2]
    );
  });

console.log("Einträge im Cache:", await askCacheSize());
Einträge im Cache: 12

Ereignis manuell erzeugen (z. B. für Tests im Worker)

// innerhalb eines Service Workers
const evt = new ExtendableMessageEvent("message", {
  data: { type: "TEST" },
  origin: self.location.origin
});
console.log(evt.data.type, evt.origin, evt.ports.length);
self.dispatchEvent(evt);
TEST https://example.com 0

// Wichtig · Fallstricke

  • Gültigkeitsbereich: Das Interface gibt es nur im ServiceWorkerGlobalScope. Auf der Seite selbst kommen Nachrichten vom Worker als gewöhnliches MessageEvent auf navigator.serviceWorker an.
  • waitUntil() nur synchron aufrufen: Die Methode muss noch während der Ereignisbehandlung aufgerufen werden, also nicht erst nach einem await. Sonst wirft sie einen InvalidStateError.
  • navigator.serviceWorker.controller kann null sein: Das passiert beim ersten Laden oder nach einem erzwungenen Neuladen (Shift+Reload). Dann besser registration.active verwenden.
  • Sicherheit: Die Herkunft der Nachricht und event.data sollten geprüft werden, bevor der Worker Befehle ausführt. Daten nie mit eval oder als HTML auswerten.
  • Daten sind Kopien: Sie werden per structured clone übertragen. Funktionen, DOM-Knoten und Klasseninstanzen samt Prototyp lassen sich so nicht übertragen und lösen einen DataCloneError aus.
  • Umgebung: Service Worker laufen nur in einem sicheren Kontext (HTTPS oder localhost). Chrome, Edge, Firefox und Safari (ab 11.1) unterstützen das Interface.