Start · Sprachen · JavaScript · Referenz · BackgroundFetchManager.fetch()

BackgroundFetchManager.fetch()

Methode

Startet einen Hintergrundabruf für eine oder mehrere URLs bzw. <code>Request</code>-Objekte, der vom Browser weitergeführt wird, auch wenn die Seite geschlossen ist.

seit JavaScript Experimentell: Chromium-Browser (Chrome/Edge 74+), Kategorie: webapi

Signatur

BackgroundFetchManager.prototype.fetch(id, requests, options)

Beschreibung

Mit fetch() des BackgroundFetchManager übergibst du große oder lang laufende Downloads, etwa Podcast-Folgen, Videos, Offline-Pakete oder Spiel-Assets, an den Browser. Der Browser führt den Download selbst aus, zeigt dem Nutzer eine Fortschrittsanzeige (z. B. als Benachrichtigung) und macht weiter, auch wenn der Tab geschlossen wird oder die Verbindung kurz abbricht. Erreichbar ist die Methode über ServiceWorkerRegistration.backgroundFetch, also nur, wenn ein Service Worker aktiv ist.

Das zurückgegebene Promise wird mit einer BackgroundFetchRegistration erfüllt. Darüber verfolgst du den Fortschritt (downloaded, downloadTotal, progress-Event) oder brichst den Download mit abort() ab. Ist der Abruf beendet, bekommt der Service Worker eines der Events backgroundfetchsuccess, backgroundfetchfail, backgroundfetchabort oder backgroundfetchclick. Dort liest du die Antworten mit registration.matchAll() aus und legst sie zum Beispiel im Cache Storage ab.

Die id ist ein von dir vergebener, eindeutiger Name. Mit BackgroundFetchManager.get(id) findest du einen laufenden Abruf später wieder, z. B. nach einem Neuladen der Seite. Über options legst du Titel und Symbole für die Anzeige im Browser fest. Außerdem kannst du die erwartete Gesamtgröße angeben, damit der Browser einen genauen Fortschrittsbalken zeigen kann.

Parameter

Name Typ Default Beschreibung
$id Pflicht string Eindeutiger, von dir vergebener Name für diesen Hintergrundabruf. Läuft bereits ein Abruf mit derselben id, wird das Promise abgelehnt.
$requests Pflicht string | Request | Array<string | Request> Eine URL, ein Request-Objekt oder ein Array davon. Alle Einträge bilden zusammen einen Abruf. Anfragen im Modus no-cors sind nicht erlaubt.
$options object {} Optionale Einstellungen für die Anzeige im Browser:
  • title (string): Titel in der Fortschrittsanzeige.
  • icons (Array<{src, sizes?, type?, label?}>): Symbole, aus denen der Browser eines auswählt.
  • downloadTotal (number, Standard 0): erwartete Gesamtgröße in Bytes. Wird sie überschritten, bricht der Browser den Abruf ab.

Rückgabewert

Typ
Promise<BackgroundFetchRegistration>
Beschreibung
Ein Promise, das mit einer BackgroundFetchRegistration für den gestarteten Abruf erfüllt wird. Es wird mit einem TypeError abgelehnt, wenn kein aktiver Service Worker vorhanden ist, eine Anfrage ungültig ist (z. B. no-cors) oder die id schon benutzt wird. Reicht der Speicherplatz nicht aus, wird es mit einer QuotaExceededError-DOMException abgelehnt.

Beispiele

Podcast-Folge im Hintergrund herunterladen

const downloadEpisode = async (episodeId, url) => {
  if (!('BackgroundFetchManager' in self)) {
    console.log('Background Fetch nicht verfügbar – normaler fetch() als Fallback');
    return fetch(url);
  }

  const swReg = await navigator.serviceWorker.ready;
  const bgFetch = await swReg.backgroundFetch.fetch(
    `episode-${episodeId}`,
    [url],
    {
      title: 'Folge 42: JavaScript im Hintergrund',
      icons: [{ src: '/icons/podcast-192.png', sizes: '192x192', type: 'image/png' }],
      downloadTotal: 58 * 1024 * 1024 // 58 MiB
    }
  );

  console.log('Gestartet:', bgFetch.id);
  return bgFetch;
};

downloadEpisode(42, '/media/episode-42.mp3');
Gestartet: episode-42

Fortschritt anzeigen und vorhandenen Abruf wiederverwenden

const startOfflinePack = async () => {
  const swReg = await navigator.serviceWorker.ready;
  const id = 'offline-pack-v3';

  // Nach einem Neuladen nicht doppelt starten
  const bgFetch = (await swReg.backgroundFetch.get(id)) ??
    await swReg.backgroundFetch.fetch(id, [
      '/offline/index.html',
      '/offline/app.js',
      new Request('/offline/maps.bin', { credentials: 'same-origin' })
    ], { title: 'Offline-Paket', downloadTotal: 120_000_000 });

  bgFetch.addEventListener('progress', () => {
    if (!bgFetch.downloadTotal) return;
    const percent = Math.round((bgFetch.downloaded / bgFetch.downloadTotal) * 100);
    console.log(`Fortschritt: ${percent} %`);
  });
};

startOfflinePack().catch((err) => console.error(err.name, err.message));
Fortschritt: 12 % Fortschritt: 47 % …

Ergebnis im Service Worker speichern (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);
    }));

    await event.updateUI({ title: 'Download abgeschlossen ✔' });
  })());
});

self.addEventListener('backgroundfetchfail', (event) => {
  event.waitUntil(event.updateUI({ title: 'Download fehlgeschlagen' }));
});

// Wichtig · Fallstricke

  • Browser-Unterstützung: Die API ist experimentell und nur in Chromium-Browsern verfügbar (Chrome, Edge, Opera, Samsung Internet). Prüfe vor der Nutzung mit 'BackgroundFetchManager' in self und sieh einen Ausweg über normales fetch() vor.
  • Sicherer Kontext: Die Methode funktioniert nur über HTTPS (oder localhost) und nur mit einem aktiven Service Worker. Warte deshalb vorher auf navigator.serviceWorker.ready.
  • Doppelte IDs: Ein zweiter Aufruf mit einer id, die gerade läuft, schlägt mit einem TypeError fehl. Prüfe vorher mit backgroundFetch.get(id), ob der Abruf schon existiert.
  • downloadTotal: Ist der Wert zu klein, bricht der Browser den Abruf ab, sobald mehr Bytes ankommen. Gib ihn nur an, wenn du die Größe genau kennst, oder großzügig aufgerundet.
  • Keine no-cors-Anfragen: Fremde Ressourcen müssen CORS erlauben. Undurchsichtige Antworten (opaque responses) werden nicht unterstützt.
  • Datenschutz: Der Browser zeigt laufende Abrufe immer sichtbar an, und der Nutzer kann sie jederzeit abbrechen. Unbemerkte Downloads im Hintergrund sind damit nicht möglich. Plane das Ereignis backgroundfetchabort mit ein.
  • Die Antworten werden nicht automatisch zwischengespeichert. Du musst sie im Service Worker selbst, z. B. mit cache.put(), dauerhaft ablegen.