Signatur
Beschreibung
waitUntil() teilt dem Browser mit, dass nach dem Ereignis noch Arbeit läuft. Solange das übergebene Promise nicht abgeschlossen ist, beendet der Browser den Service Worker nicht. Ohne diesen Aufruf darf der Browser den Worker direkt nach dem synchronen Teil des Event-Handlers stoppen. Asynchrone Vorgänge wie das Befüllen des Caches würden dann mittendrin abbrechen.
Die wichtigsten Einsatzorte sind:
install: Dateien vorab in den Cache laden (Precaching). Wird das Promise abgelehnt, gilt die Installation als fehlgeschlagen und der Worker wird verworfen.activate: veraltete Caches löschen oder Daten migrieren. Funktionale Ereignisse wiefetchwerden erst zugestellt, wenn das Promise abgeschlossen ist.push,notificationclick,sync,message: Benachrichtigungen anzeigen, Fenster öffnen oder Daten im Hintergrund synchronisieren.
Man kann waitUntil() mehrmals aufrufen. Der Browser wartet dann, bis alle übergebenen Promises abgeschlossen sind. Bei install führt schon ein einziges abgelehntes Promise dazu, dass die Installation fehlschlägt.
Beim fetch-Ereignis (ein FetchEvent, das von ExtendableEvent erbt) verzögert waitUntil() nicht die Antwort. Es hält den Worker nur für Hintergrundarbeit am Leben, etwa um den Cache nach der Antwort zu aktualisieren. Für die Antwort selbst ist respondWith() zuständig.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $promise Pflicht | Promise<any> | Ein Promise, das die laufende Arbeit darstellt. Der Browser hält den Worker am Leben, bis es erfüllt oder abgelehnt ist. Wird kein Promise übergeben, wird der Wert wie mit Promise.resolve() in ein Promise umgewandelt. |
Rückgabewert
undefined).Beispiele
Precaching im install-Ereignis
// sw.js
const CACHE_NAME = 'app-v2';
const ASSETS = ['/', '/index.html', '/styles.css', '/app.js', '/logo.svg'];
self.addEventListener('install', (event) => {
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE_NAME);
await cache.addAll(ASSETS); // schlägt ein Request fehl, schlägt die Installation fehl
console.log('Precaching abgeschlossen');
})()
);
});
Alte Caches im activate-Ereignis aufräumen
const CURRENT_CACHES = ['app-v2'];
self.addEventListener('activate', (event) => {
event.waitUntil(
(async () => {
const keys = await caches.keys();
await Promise.all(
keys
.filter((key) => !CURRENT_CACHES.includes(key))
.map((key) => caches.delete(key))
);
await self.clients.claim(); // sofort Kontrolle über offene Seiten übernehmen
console.log('Alte Caches entfernt:', keys.filter((k) => !CURRENT_CACHES.includes(k)));
})()
);
});
Push-Benachrichtigung anzeigen
self.addEventListener('push', (event) => {
const data = event.data?.json() ?? { title: 'Neuigkeiten', body: 'Es gibt etwas Neues.' };
event.waitUntil(
self.registration.showNotification(data.title, {
body: data.body,
icon: '/icons/icon-192.png',
})
);
});
Stale-While-Revalidate: Cache im fetch-Ereignis im Hintergrund aktualisieren
self.addEventListener('fetch', (event) => {
if (event.request.method !== 'GET') return;
event.respondWith(
(async () => {
const cache = await caches.open('runtime');
const cached = await cache.match(event.request);
const networkUpdate = fetch(event.request).then(async (response) => {
if (response.ok) await cache.put(event.request, response.clone());
return response;
});
// Worker am Leben halten, bis der Cache aktualisiert ist
event.waitUntil(networkUpdate.catch(() => {}));
return cached ?? networkUpdate;
})()
);
});
// Wichtig · Fallstricke
- Synchron aufrufen:
waitUntil()muss während der Ereigniszustellung aufgerufen werden, also im synchronen Teil des Handlers oder solange ein bereits übergebenes Promise noch offen ist. Ein späterer Aufruf, etwa nach einemawaitohne vorherigeswaitUntil(), wirft einenInvalidStateError(DOMException). - Kein
async-Handler als Ersatz: Einasync-Event-Listener allein hält den Worker nicht am Leben. Den Browser interessiert das vom Listener zurückgegebene Promise nicht. Die asynchrone Arbeit muss deshalb immer anwaitUntil()übergeben werden. - Ablehnung bei
install: Ein abgelehntes Promise lässt die Installation scheitern.cache.addAll()ist atomar: Ist auch nur eine einzige URL nicht erreichbar (z. B. 404), schlägt die gesamte Installation fehl. - Zeitlimits: Browser setzen eigene Obergrenzen für die Lebensdauer eines Workers, typischerweise wenige Minuten. Sehr lange Aufgaben können trotz
waitUntil()abgebrochen werden. Für große Übertragungen eignen sich Background Sync oder Background Fetch. - Kompatibilität: Nur in Service-Worker-Kontexten verfügbar (Chrome, Edge, Firefox, Safari 11.1+). Service Worker setzen HTTPS voraus (Ausnahme:
localhost). Im privaten Modus von Firefox sind Service Worker nicht verfügbar.