Start · Sprachen · JavaScript · Referenz · ServiceWorkerContainer.ready

ServiceWorkerContainer.ready

Eigenschaft

Liefert ein <code>Promise&lt;ServiceWorkerRegistration&gt;</code>, das sich erfüllt, sobald für die aktuelle Seite ein aktiver Service Worker vorhanden ist.

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

Signatur

get ServiceWorkerContainer.ready

Beschreibung

Die schreibgeschützte Eigenschaft navigator.serviceWorker.ready gibt ein Promise zurück. Es erfüllt sich mit der ServiceWorkerRegistration, deren Geltungsbereich (scope) die aktuelle Seite umfasst und die einen aktiven Worker besitzt (registration.active ist dann nicht null). Damit lässt sich Code, der einen einsatzbereiten Service Worker braucht, sauber verzögern.

Typische Einsatzfälle sind Funktionen, die nur über eine aktive Registrierung funktionieren: Push-Abonnements mit registration.pushManager.subscribe(), Hintergrund-Synchronisation mit registration.sync.register(), Benachrichtigungen per registration.showNotification() oder Nachrichten an registration.active.postMessage().

Wichtig: Das Promise wird niemals abgelehnt. Wenn keine passende Registrierung existiert oder die Registrierung fehlschlägt, bleibt es für immer ausstehend (pending). Es ist also kein Fehlerindikator. Außerdem steht es nicht dafür, dass die Seite schon von diesem Worker kontrolliert wird. Dafür ist navigator.serviceWorker.controller bzw. das Ereignis controllerchange zuständig.

Rückgabewert

Typ
Promise<ServiceWorkerRegistration>
Beschreibung
Ein Promise, das sich mit der aktiven ServiceWorkerRegistration für die aktuelle Seite erfüllt. Es liefert bei jedem Zugriff dasselbe Promise-Objekt, solange sich die Registrierung nicht ändert, und wird nie abgelehnt.

Beispiele

Registrieren und auf den aktiven Worker warten

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .catch((err) => console.error('Registrierung fehlgeschlagen:', err));

  const registration = await navigator.serviceWorker.ready;
  console.log('Aktiver Worker:', registration.active.state);
  console.log('Scope:', registration.scope);
}
Aktiver Worker: activated Scope: https://example.com/

Push-Benachrichtigungen abonnieren

const urlBase64ToUint8Array = (base64) => {
  const padding = '='.repeat((4 - (base64.length % 4)) % 4);
  const raw = atob((base64 + padding).replace(/-/g, '+').replace(/_/g, '/'));
  return Uint8Array.from(raw, (c) => c.charCodeAt(0));
};

const subscribeToPush = async (vapidPublicKey) => {
  const registration = await navigator.serviceWorker.ready;
  const subscription = await registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: urlBase64ToUint8Array(vapidPublicKey)
  });
  await fetch('/api/push/subscribe', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(subscription)
  });
  return subscription;
};

Nachricht an den Worker senden – mit Timeout gegen ewiges Warten

const withTimeout = (promise, ms) => Promise.race([
  promise,
  new Promise((_, reject) =>
    setTimeout(() => reject(new Error('Kein aktiver Service Worker')), ms))
]);

try {
  const registration = await withTimeout(navigator.serviceWorker.ready, 5000);
  registration.active.postMessage({ type: 'CACHE_URLS', urls: ['/offline.html'] });
  console.log('Nachricht gesendet');
} catch (err) {
  console.warn(err.message);
}
Nachricht gesendet

// Wichtig · Fallstricke

  • Keine Ablehnung: ready wird nie abgelehnt. Schlägt register() fehl oder liegt die Seite außerhalb jedes Scopes, bleibt ein await für immer hängen. Fehler behandelt man am register()-Promise, und bei Bedarf sichert man mit einem Timeout ab (siehe Beispiel 3).
  • Aktiv heißt nicht kontrollierend: Beim ersten Laden ist navigator.serviceWorker.controller oft noch null, obwohl ready schon erfüllt ist. Abhilfe: clients.claim() im Worker oder auf controllerchange warten.
  • Sicherer Kontext nötig: Service Worker gibt es nur über HTTPS (oder localhost). In privaten Fenstern mancher Browser (z. B. älteres Firefox) ist navigator.serviceWorker undefined. Deshalb vorher mit 'serviceWorker' in navigator prüfen.
  • Scope beachten: Ein Worker unter /app/sw.js gilt standardmäßig nur für /app/. Seiten außerhalb davon erhalten über ready keine Registrierung.
  • Top-Level-await funktioniert nur in ES-Modulen (<script type="module">).