Signatur
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, einClient,ServiceWorkeroderMessagePort. Damit kann man gezielt antworten.origin: der Ursprung (Origin) des Absenders.lastEventId: bei Service-Worker-Nachrichten meist ein leerer String.ports: ein Array der übertragenenMessagePort-Objekte, z. B. für eine Antwort über einenMessageChannel.
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
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" });
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());
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);
// Wichtig · Fallstricke
- Gültigkeitsbereich: Das Interface gibt es nur im
ServiceWorkerGlobalScope. Auf der Seite selbst kommen Nachrichten vom Worker als gewöhnlichesMessageEventaufnavigator.serviceWorkeran. waitUntil()nur synchron aufrufen: Die Methode muss noch während der Ereignisbehandlung aufgerufen werden, also nicht erst nach einemawait. Sonst wirft sie einenInvalidStateError.navigator.serviceWorker.controllerkannnullsein: Das passiert beim ersten Laden oder nach einem erzwungenen Neuladen (Shift+Reload). Dann besserregistration.activeverwenden.- Sicherheit: Die Herkunft der Nachricht und
event.datasollten geprüft werden, bevor der Worker Befehle ausführt. Daten nie mitevaloder 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
DataCloneErroraus. - Umgebung: Service Worker laufen nur in einem sicheren Kontext (HTTPS oder
localhost). Chrome, Edge, Firefox und Safari (ab 11.1) unterstützen das Interface.