Signatur
Beschreibung
Die Eigenschaft waiting eines ServiceWorkerRegistration-Objekts verweist auf einen Service Worker, der fertig installiert ist, aber noch wartet, bis er aktiviert werden darf. Sein state ist "installed". Gibt es keinen solchen Worker, ist der Wert null.
Ein neuer Service Worker bleibt standardmäßig so lange im Wartezustand, bis keine Seite (kein Client) mehr vom alten, aktiven Worker gesteuert wird. So laufen nie zwei Versionen gleichzeitig für dieselbe Seite. Erst wenn alle Tabs geschlossen sind oder der Worker self.skipWaiting() aufruft, wird er aktiv und erscheint unter registration.active.
In der Praxis nutzt man waiting vor allem für ein „Update verfügbar“-Banner: Die Seite erkennt eine wartende neue Version, fragt den Nutzer und schickt dem wartenden Worker per postMessage() den Befehl, skipWaiting() auszuführen. Danach lädt man die Seite neu, sobald das Ereignis controllerchange eintritt.
Zusammen mit installing und active bildet waiting die drei Lebenszyklus-Stufen, die eine Registrierung gleichzeitig halten kann.
Rückgabewert
ServiceWorker mit state === "installed" oder null, wenn aktuell kein Worker wartet.Beispiele
Prüfen, ob eine neue Version wartet
const registration = await navigator.serviceWorker.getRegistration();
if (registration?.waiting) {
console.log('Neue Version wartet:', registration.waiting.scriptURL);
console.log('Status:', registration.waiting.state);
} else {
console.log('Keine wartende Version.');
}
„Update verfügbar“-Banner mit skipWaiting
// Seite (main.js)
const showUpdateBanner = (worker) => {
if (confirm('Neue Version verfügbar. Jetzt aktualisieren?')) {
worker.postMessage({ type: 'SKIP_WAITING' });
}
};
const registration = await navigator.serviceWorker.register('/sw.js');
// Fall 1: Beim Laden wartet bereits ein Worker
if (registration.waiting) {
showUpdateBanner(registration.waiting);
}
// Fall 2: Ein Update wird während der Sitzung gefunden
registration.addEventListener('updatefound', () => {
const newWorker = registration.installing;
newWorker?.addEventListener('statechange', () => {
// Nur als Update werten, wenn bereits ein Controller existiert
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
showUpdateBanner(registration.waiting);
}
});
});
// Nach der Aktivierung einmalig neu laden
let reloaded = false;
navigator.serviceWorker.addEventListener('controllerchange', () => {
if (reloaded) return;
reloaded = true;
window.location.reload();
});
// Service Worker (sw.js)
// self.addEventListener('message', (event) => {
// if (event.data?.type === 'SKIP_WAITING') self.skipWaiting();
// });
Alle Lebenszyklus-Stufen einer Registrierung auflisten
const registrations = await navigator.serviceWorker.getRegistrations();
for (const reg of registrations) {
console.table({
scope: reg.scope,
installing: reg.installing?.state ?? '–',
waiting: reg.waiting?.state ?? '–',
active: reg.active?.state ?? '–'
});
}
// Wichtig · Fallstricke
- Erstinstallation: Gibt es noch keinen aktiven Worker, bleibt der neue nicht in der Warteschlange, sondern wird sofort aktiviert.
waitingist dann meistnull. Prüfen Sie deshalbnavigator.serviceWorker.controller, damit Sie ein Update nicht mit der ersten Installation verwechseln. - Neuladen genügt nicht: Ein einfaches Neuladen (F5) aktiviert den wartenden Worker oft nicht, weil der alte Client während der Navigation weiterbesteht. Erst wenn alle Tabs geschlossen sind oder
skipWaiting()aufgerufen wird, geht es weiter. - Vorsicht bei
skipWaiting(): Offene Seiten können dann mit einem neuen Worker weiterlaufen, der Ressourcen einer anderen Version ausliefert. Deshalb nachcontrollerchangeneu laden und einen Merker gegen Endlosschleifen setzen. - Der Wert ist nur eine Momentaufnahme. Wer auf Änderungen reagieren will, nutzt
updatefoundundstatechange, statt die Eigenschaft wiederholt abzufragen. - Service Worker gibt es nur in sicheren Kontexten (HTTPS oder
localhost). In privaten Fenstern mancher Browser, z. B. Firefox, istnavigator.serviceWorkereventuell nicht verfügbar.