Signatur
Beschreibung
Ein ServiceWorker-Objekt steht für einen einzelnen Service Worker, der unter einer URL registriert ist. Die Instanz legst du nie selbst mit new an. Du bekommst sie über navigator.serviceWorker.controller (der Worker, der die aktuelle Seite steuert) oder über die Eigenschaften installing, waiting und active einer ServiceWorkerRegistration.
Das Interface hat nur wenige Mitglieder:
scriptURL– die URL des Worker-Skripts (nur lesbar)state– der Lebenszyklus-Zustand:"parsed","installing","installed","activating","activated"oder"redundant"postMessage(message, transfer)– schickt dem Worker eine Nachricht, die dieser immessage-Event erhältstatechange-Event bzw.onstatechange– wird ausgelöst, sobald sichstateänderterror-Event bzw.onerror– wird bei Fehlern im Worker ausgelöst
Du brauchst das Interface vor allem an zwei Stellen: um den Update-Ablauf zu steuern (etwa einen Hinweis „Neue Version verfügbar“ anzeigen, sobald ein neuer Worker installed ist) und um zwischen Seite und Worker zu kommunizieren (etwa das Signal SKIP_WAITING schicken oder Caches gezielt leeren).
Service Worker laufen nur in einem sicheren Kontext, also über HTTPS oder auf localhost. Ihr Lebenszyklus ist unabhängig von einzelnen Tabs: Der Browser kann einen Worker jederzeit beenden und bei Bedarf neu starten.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $message Pflicht | any | Nur bei postMessage(): Die Daten, die an den Worker gehen. Sie werden mit dem Structured-Clone-Algorithmus kopiert, deshalb sind keine Funktionen und keine DOM-Knoten erlaubt. |
|
| $transfer | Transferable[] | { transfer: Transferable[] } | [] | Nur bei postMessage(): Objekte, deren Besitz an den Worker übergeht, statt dass sie kopiert werden, z. B. MessagePort oder ArrayBuffer. |
Beispiele
Worker registrieren und aktive Instanz auslesen
const init = async () => {
if (!('serviceWorker' in navigator)) return;
const registration = await navigator.serviceWorker.register('/sw.js');
// Welcher Worker gerade vorhanden ist, hängt vom Zustand ab
const worker = registration.installing ?? registration.waiting ?? registration.active;
console.log(worker.scriptURL, worker.state);
};
init();
Lebenszyklus mit statechange verfolgen und Update-Hinweis zeigen
const registration = await navigator.serviceWorker.register('/sw.js');
registration.addEventListener('updatefound', () => {
const newWorker = registration.installing;
const onStateChange = () => {
console.log('Neuer Zustand:', newWorker.state);
// Ein alter Controller ist vorhanden, also handelt es sich um ein Update
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
console.log('Neue Version bereit – bitte neu laden.');
newWorker.removeEventListener('statechange', onStateChange);
}
};
newWorker.addEventListener('statechange', onStateChange);
});
Wartenden Worker per postMessage sofort aktivieren
// Seite:
const registration = await navigator.serviceWorker.getRegistration();
registration?.waiting?.postMessage({ type: 'SKIP_WAITING' });
navigator.serviceWorker.addEventListener('controllerchange', () => {
window.location.reload();
});
// sw.js:
// self.addEventListener('message', (event) => {
// if (event.data?.type === 'SKIP_WAITING') self.skipWaiting();
// });
Antwort vom Worker über einen MessageChannel
const askWorker = (payload) => new Promise((resolve) => {
const { port1, port2 } = new MessageChannel();
port1.onmessage = (event) => resolve(event.data);
// port2 geht per transfer an den Worker über
navigator.serviceWorker.controller?.postMessage(payload, [port2]);
});
// sw.js: event.ports[0].postMessage({ version: '1.4.0' });
const answer = await askWorker({ type: 'GET_VERSION' });
console.log(answer.version);
// Wichtig · Fallstricke
- Controller ist oft
null: Beim ersten Laden steuert noch kein Worker die Seite, und nach einem harten Neuladen (Umschalt+F5) ebenfalls nicht.navigator.serviceWorker.controllerist dannnull. Nutze Optional Chaining oder warte aufnavigator.serviceWorker.ready. redundant: Dieser Zustand bedeutet, dass der Worker ersetzt wurde oder die Installation fehlgeschlagen ist. Eine solche Referenz ist nicht mehr zu gebrauchen.- Nachrichten immer prüfen: Prüfe im Worker
event.originbzw.event.sourceund das Format vonevent.data. Führe niemals empfangene Daten als Code aus (eval). - Nur sicherer Kontext: Die API funktioniert nur über HTTPS oder auf
localhost. In manchen privaten Modi fehlt sie, zum Beispiel im privaten Modus von Firefox. Frage sie deshalb immer mit'serviceWorker' in navigatorab. - Kein dauerhafter Zustand im Worker: Der Browser kann den Worker jederzeit beenden. Globale Variablen darin gehen dann verloren. Speichere Daten stattdessen in IndexedDB oder in der Cache API.
- Die Form
postMessage(message, { transfer })mit Options-Objekt unterstützen neuere Browser. Die Array-Form funktioniert überall.