Signatur
Beschreibung
Die Schnittstelle BackgroundFetchRecord gehört zur Background Fetch API. Mit dieser API kann ein Service Worker große Downloads wie Videos, Podcasts oder Spiel-Assets im Hintergrund erledigen, auch wenn der Nutzer die Seite schon geschlossen hat. Ein Background Fetch kann mehrere Anfragen enthalten. Für jede Anfrage gibt es genau einen BackgroundFetchRecord.
Einen Record erzeugt man nicht selbst. Man bekommt ihn über BackgroundFetchRegistration.match() (ein Record) oder BackgroundFetchRegistration.matchAll() (ein Array von Records). Die Schnittstelle hat nur zwei schreibgeschützte Eigenschaften:
request: dasRequest-Objekt der Anfrage, zum Beispiel für den Zugriff aufrequest.url.responseReady: einPromise<Response>. Es wird erfüllt, sobald die Antwort vollständig da ist, und abgelehnt, wenn die Anfrage fehlschlägt oder abgebrochen wird.
Am häufigsten nutzt man die Records im Service Worker, und zwar im Handler für backgroundfetchsuccess. Dort liest man die Antworten aus und legt sie zum Beispiel mit der Cache API dauerhaft ab. Im Handler für backgroundfetchfail kann man prüfen, welche Teilanfragen nicht geklappt haben.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $request | Request | Eigenschaft (schreibgeschützt): die ursprüngliche Anfrage dieses Records. | |
| $responseReady | Promise<Response> | Eigenschaft (schreibgeschützt): Promise, das mit der vollständigen Response erfüllt wird. Schlägt die Anfrage fehl oder wird sie abgebrochen, wird es abgelehnt. |
Rückgabewert
registration.match() (als Promise<BackgroundFetchRecord | undefined>) oder aus registration.matchAll() (als Promise<BackgroundFetchRecord[]>).Beispiele
Background Fetch starten (Seite)
// Im Seiten-Skript: Download im Hintergrund anstoßen
const startDownload = async () => {
const swReg = await navigator.serviceWorker.ready;
if (!('backgroundFetch' in swReg)) {
console.log('Background Fetch wird nicht unterstützt');
return;
}
const bgFetch = await swReg.backgroundFetch.fetch(
'podcast-folge-42',
['/media/folge-42.mp3', '/media/folge-42-cover.jpg'],
{ title: 'Folge 42 wird geladen', downloadTotal: 60 * 1024 * 1024 }
);
console.log('Gestartet:', bgFetch.id);
};
startDownload();
Alle Records nach Erfolg im Cache speichern (Service Worker)
// sw.js
self.addEventListener('backgroundfetchsuccess', (event) => {
const bgFetch = event.registration;
event.waitUntil((async () => {
const cache = await caches.open('downloads');
const records = await bgFetch.matchAll();
await Promise.all(records.map(async (record) => {
const response = await record.responseReady;
await cache.put(record.request, response);
console.log('Gespeichert:', record.request.url);
}));
await event.updateUI({ title: 'Download abgeschlossen' });
})());
});
Einzelnen Record per URL abfragen
// sw.js
self.addEventListener('backgroundfetchsuccess', (event) => {
event.waitUntil((async () => {
const record = await event.registration.match('/media/folge-42-cover.jpg');
if (!record) return;
const response = await record.responseReady;
console.log(record.request.method, response.status, response.headers.get('content-type'));
})());
});
Fehlgeschlagene Teilanfragen erkennen
// sw.js
self.addEventListener('backgroundfetchfail', (event) => {
event.waitUntil((async () => {
const records = await event.registration.matchAll();
for (const record of records) {
try {
const response = await record.responseReady;
if (!response.ok) console.warn('HTTP-Fehler', response.status, record.request.url);
} catch (err) {
console.warn('Keine Antwort für', record.request.url, err.name);
}
}
console.log('Grund:', event.registration.failureReason);
})());
});
// Wichtig · Fallstricke
- Experimentell und nur in Chromium: Die API gibt es in Chrome, Edge und Opera (ab Version 74). Firefox und Safari unterstützen sie nicht. Prüfe deshalb immer mit
'backgroundFetch' in registration, ob sie verfügbar ist, und sieh einen Fallback vor, etwa ein normalesfetch(). - Die API funktioniert nur in einem sicheren Kontext (HTTPS) und braucht einen aktiven Service Worker.
- Records sind nur begrenzt verfügbar:
match()undmatchAll()funktionieren nur, solangeregistration.recordsAvailableden Werttruehat. Das ist im Wesentlichen innerhalb der Handler fürbackgroundfetchsuccessundbackgroundfetchfailder Fall. Ist der Handler durchgelaufen, werfen beide Methoden einenInvalidStateError. Verpacke die Verarbeitung deshalb inevent.waitUntil()und speichere die Antworten dauerhaft, zum Beispiel in der Cache API. - Den Body einer
Responsekann man nur einmal lesen. Wenn du die Antwort cachen und gleichzeitig auswerten willst, arbeite mitresponse.clone(). responseReadywird auch bei HTTP-Fehlern wie 404 erfüllt. Prüfe deshalb zusätzlichresponse.ok. Abgelehnt wird das Promise nur, wenn gar keine Antwort vorliegt, etwa nach einem Abbruch.- Es gibt keinen öffentlichen Konstruktor. Ein Aufruf von
new BackgroundFetchRecord()wirft einenTypeError.