Signatur
Beschreibung
Das Ereignis controllerchange wird auf dem ServiceWorkerContainer (navigator.serviceWorker) ausgelöst, sobald das Dokument einen neuen steuernden Service Worker erhält. Das passiert zum Beispiel, wenn ein neuer Worker aktiviert wird und über clients.claim() die Kontrolle über bereits offene Seiten übernimmt, oder wenn ein wartender Worker per skipWaiting() den alten ersetzt.
Typischerweise nutzt man das Ereignis für Update-Abläufe in Progressive Web Apps. Der Nutzer bestätigt „Neue Version verfügbar – neu laden?“, die Seite schickt dem wartenden Worker eine Nachricht, damit er skipWaiting() aufruft, und sobald controllerchange eintrifft, lädt die Seite neu. So laufen danach alle Anfragen über den neuen Worker und seinen neuen Cache.
Registrieren kann man den Handler mit navigator.serviceWorker.addEventListener("controllerchange", handler) oder über die Eigenschaft navigator.serviceWorker.oncontrollerchange. Der Handler bekommt ein einfaches Event ohne weitere Daten. Den neuen Worker liest man aus navigator.serviceWorker.controller aus.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "controllerchange". |
|
| $handler Pflicht | (event: Event) => void | Callback-Funktion. Sie erhält ein normales Event; den neuen Controller liest man über navigator.serviceWorker.controller aus. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie { once: true }, damit der Handler nur einmal läuft. Das ist beim Neuladen der Seite sinnvoll. |
Rückgabewert
addEventListener gibt nichts zurück. Das Ereignisobjekt ist ein einfaches Event ohne zusätzliche Eigenschaften.Beispiele
Auf Controller-Wechsel reagieren (addEventListener)
if ('serviceWorker' in navigator) {
navigator.serviceWorker.addEventListener('controllerchange', () => {
const sw = navigator.serviceWorker.controller;
console.log('Neuer Controller:', sw?.scriptURL);
});
navigator.serviceWorker.register('/sw.js');
}
Update-Ablauf: skipWaiting auslösen und einmal neu laden
// Seite (main.js)
const reg = await navigator.serviceWorker.register('/sw.js');
const aktualisieren = (worker) => {
if (confirm('Neue Version verfügbar. Jetzt aktualisieren?')) {
worker.postMessage({ type: 'SKIP_WAITING' });
}
};
if (reg.waiting) aktualisieren(reg.waiting);
reg.addEventListener('updatefound', () => {
const neu = reg.installing;
neu?.addEventListener('statechange', () => {
if (neu.state === 'installed' && navigator.serviceWorker.controller) {
aktualisieren(neu);
}
});
});
let neuGeladen = false;
navigator.serviceWorker.addEventListener('controllerchange', () => {
if (neuGeladen) return; // Endlosschleife verhindern
neuGeladen = true;
window.location.reload();
});
// Service Worker (sw.js)
// self.addEventListener('message', (e) => {
// if (e.data?.type === 'SKIP_WAITING') self.skipWaiting();
// });
Variante mit on-Property und Handler wieder entfernen
const onWechsel = () => {
console.log('Seite wird jetzt gesteuert von:',
navigator.serviceWorker.controller?.scriptURL);
};
// Per Eigenschaft (überschreibt einen früheren Handler)
navigator.serviceWorker.oncontrollerchange = onWechsel;
// Später wieder abmelden
navigator.serviceWorker.oncontrollerchange = null;
// Alternativ mit addEventListener / removeEventListener
navigator.serviceWorker.addEventListener('controllerchange', onWechsel);
navigator.serviceWorker.removeEventListener('controllerchange', onWechsel);
// Wichtig · Fallstricke
- Wird beim ersten Besuch nicht automatisch ausgelöst: Nach der ersten Registrierung steuert der Worker die aktuelle Seite erst nach einem Neuladen. Ruft der Worker aber in seinem
activate-Handlerclients.claim()auf, feuertcontrollerchangeschon beim ersten Besuch. Wer dann blind neu lädt, lädt beim Erstbesuch unnötig neu. - Neulade-Schleifen: Mit den DevTools-Optionen „Update on reload“ oder bei mehrfachem Auslösen kann ein Handler, der
location.reload()aufruft, eine Schleife erzeugen. Dagegen hilft ein Merker (siehe Beispiel) oder{ once: true }. - Controller kann
nullwerden: Wird die Registrierung entfernt (unregister()), istnavigator.serviceWorker.controllerdanachnull. Vor dem Zugriff also prüfen. - Alle Tabs sind betroffen: Das Ereignis tritt in jedem Tab auf, den der neue Worker übernimmt. Ein automatisches Neuladen kann in anderen Tabs Formulareingaben verwerfen.
- Kompatibilität: Wird in allen modernen Browsern unterstützt (Chrome, Edge, Firefox, Safari ab 11.1). Service Worker brauchen einen sicheren Kontext (HTTPS oder
localhost). In privaten Fenstern mancher Browser (z. B. Firefox) istnavigator.serviceWorkernicht verfügbar. Vorher mit'serviceWorker' in navigatorprüfen.