Start · Sprachen · JavaScript · Referenz · ServiceWorker: statechange

ServiceWorker: statechange

Ereignis

Wird an einem <code>ServiceWorker</code>-Objekt ausgelöst, sobald sich seine Eigenschaft <code>state</code> ändert, z. B. von <code>installing</code> zu <code>installed</code>.

seit JavaScript Baseline: alle modernen Browser (seit 2018) Kategorie: webapi

Signatur

serviceWorker.addEventListener("statechange", handler)

Beschreibung

Das Ereignis statechange wird an einer ServiceWorker-Instanz ausgelöst, sobald sich der Wert von ServiceWorker.state ändert. Ein Service Worker durchläuft dabei die Zustände parsed, installing, installed, activating, activated und schließlich eventuell redundant.

Typischerweise nutzt man das Ereignis auf der Seite (nicht im Worker-Skript selbst), um den Lebenszyklus eines neu registrierten oder aktualisierten Workers zu verfolgen. Ein klassischer Anwendungsfall ist der Hinweis „Neue Version verfügbar – neu laden?“: Sobald ein Update-Worker den Zustand installed erreicht und bereits ein navigator.serviceWorker.controller existiert, wartet eine neue Version auf ihre Aktivierung.

Den Handler registriert man entweder mit addEventListener("statechange", handler) oder über die Eigenschaft onstatechange. Das übergebene Objekt ist ein einfaches Event; den neuen Zustand liest man über event.target.state aus. Das Ereignis ist nicht abbrechbar und steigt nicht auf (kein Bubbling).

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "statechange".
$handler Pflicht (event: Event) => void Callback, der bei jeder Zustandsänderung aufgerufen wird. event.target ist der betroffene ServiceWorker; der neue Zustand steht in event.target.state.
$options boolean | AddEventListenerOptions false Optionen wie once oder signal (zum Entfernen per AbortController).

Beispiele

Lebenszyklus eines neu installierten Workers verfolgen

const registration = await navigator.serviceWorker.register('/sw.js');
const worker = registration.installing ?? registration.waiting ?? registration.active;

if (worker) {
  console.log('Startzustand:', worker.state);
  worker.addEventListener('statechange', (event) => {
    console.log('Neuer Zustand:', event.target.state);
  });
}
Startzustand: installing Neuer Zustand: installed Neuer Zustand: activating Neuer Zustand: activated

Hinweis „Update verfügbar“ anzeigen

const registration = await navigator.serviceWorker.register('/sw.js');

registration.addEventListener('updatefound', () => {
  const newWorker = registration.installing;
  if (!newWorker) return;

  newWorker.addEventListener('statechange', () => {
    // installed + vorhandener Controller = neue Version wartet
    if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
      const banner = document.querySelector('#update-banner');
      banner.hidden = false;
      banner.querySelector('button').addEventListener('click', () => {
        newWorker.postMessage({ type: 'SKIP_WAITING' });
      }, { once: true });
    }
  });
});

// Nach Übernahme durch den neuen Worker neu laden
navigator.serviceWorker.addEventListener('controllerchange', () => location.reload());

Über onstatechange und Handler wieder entfernen

const registration = await navigator.serviceWorker.register('/sw.js');
const worker = registration.installing;

if (worker) {
  // Variante 1: on-Property
  worker.onstatechange = () => {
    if (worker.state === 'activated') {
      console.log('Worker aktiv – Offline-Modus bereit');
      worker.onstatechange = null; // Handler entfernen
    }
  };

  // Variante 2: addEventListener + removeEventListener
  const onRedundant = () => {
    if (worker.state === 'redundant') {
      console.warn('Installation fehlgeschlagen oder ersetzt');
      worker.removeEventListener('statechange', onRedundant);
    }
  };
  worker.addEventListener('statechange', onRedundant);
}
Worker aktiv – Offline-Modus bereit

// Wichtig · Fallstricke

  • Nur Änderungen: Für den Zustand, den der Worker bei der Registrierung des Handlers schon hat, wird kein Ereignis ausgelöst. Prüfe daher immer zuerst worker.state direkt.
  • Zustände können übersprungen werden: Schlägt die Installation fehl, wechselt der Worker direkt zu redundant. Verlasse dich nicht darauf, jeden Zwischenzustand mitzubekommen.
  • Richtiges Objekt wählen: statechange wird am ServiceWorker ausgelöst, nicht an der ServiceWorkerRegistration und nicht an navigator.serviceWorker. Für neue Versionen erst auf updatefound hören und dann den Handler an registration.installing hängen.
  • Kein Ersatz für Worker-Ereignisse: Im Worker-Skript selbst verwendet man install und activate statt statechange.
  • Kompatibilität: Wird in allen modernen Browsern unterstützt. Service Worker laufen nur in sicheren Kontexten (HTTPS oder localhost) und sind im privaten Modus mancher Browser (z. B. ältere Firefox-Versionen) nicht verfügbar. Prüfe vorab mit 'serviceWorker' in navigator.