Jetzt neu: Hintergrundabruf

Jake Archibald
Jake Archibald

2015 haben wir die Hintergrundsynchronisierung eingeführt, mit der Service Worker warten, bis der Nutzer eine Verbindung hat. Das bedeutet, dass Nutzende Nachricht senden, klicken Sie auf "Senden" und verlassen Sie die Website in dem Wissen, dass die Nachricht entweder jetzt oder zu dem Zeitpunkt gesendet wird, Konnektivität haben.

Dies ist eine nützliche Funktion, erfordert aber, dass der Service Worker für die Dauer des Fetch". Für kurze Arbeitsschritte wie das Senden einer Nachricht ist das kein Problem, aber wenn die Aufgabe zu lange beendet, da der Browser den Service Worker beendet, da dies ein Risiko für den Datenschutz Akku.

Was ist, wenn Sie etwas herunterladen müssen, das lange dauert, z. B. einen Film, Podcasts oder Level eines Spiels. Dafür ist der Hintergrundabruf vorgesehen.

Der Hintergrundabruf ist seit Chrome 74 standardmäßig verfügbar.

Hier ist eine kurze zweiminütige Demo, die den herkömmlichen Stand der Dinge im Vergleich zur Verwendung von Background Fetch zeigt:

Probieren Sie die Demo selbst aus und sehen Sie sich den Code an.

Funktionsweise

So funktioniert ein Hintergrundabruf:

  1. Sie weisen den Browser an, eine Gruppe von Abrufen im Hintergrund auszuführen.
  2. Der Browser ruft diese Daten ab und zeigt dem Nutzer den Fortschritt an.
  3. Sobald der Abruf abgeschlossen oder fehlgeschlagen ist, öffnet der Browser Ihren Service Worker und löst ein Ereignis aus um Ihnen zu erzählen, was passiert ist. Hier entscheiden Sie gegebenenfalls, was mit den Antworten geschehen soll.

Wenn der Nutzer die Seiten Ihrer Website nach Schritt 1 schließt, wird der Download fortgesetzt. Weil der Abruf gut sichtbar ist und leicht abgebrochen werden kann. im Hintergrund synchronisieren. Da der Service Worker nicht ständig ausgeführt wird, dass es das System missbrauchen und z. B. Bitcoin im Hintergrund abbauen könnte.

Auf einigen Plattformen (z. B. Android) kann der Browser nach Schritt 1 geschlossen werden, da der kann der Browser den Abruf an das Betriebssystem übergeben.

Wenn der Nutzer den Download offline startet oder während des Downloads offline geht, wird der Hintergrund Fetch wird pausiert und später fortgesetzt.

Mit der API

Funktionserkennung

Wie bei jeder neuen Funktion möchten Sie herausfinden, ob der Browser dies unterstützt. Für den Hintergrundabruf so einfach wie:

if ('BackgroundFetchManager' in self) {
  // This browser supports Background Fetch!
}

Hintergrundabruf starten

Die Haupt-API hängt von einer Service Worker-Registrierung ab. Stellen Sie daher zunächst sicher, dass Sie einen Service Worker registriert haben. Dann:

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.fetch('my-fetch', ['/ep-5.mp3', 'ep-5-artwork.jpg'], {
    title: 'Episode 5: Interesting things.',
    icons: [{
      sizes: '300x300',
      src: '/ep-5-icon.png',
      type: 'image/png',
    }],
    downloadTotal: 60 * 1024 * 1024,
  });
});

Für backgroundFetch.fetch sind drei Argumente erforderlich:

Parameter
id string
Identifiziert diesen Hintergrundabruf eindeutig.

backgroundFetch.fetch lehnt ab, wenn die ID mit einem vorhandenen Hintergrund übereinstimmt Fetch".

requests Array<Request|string>
Die Dinge, die abgerufen werden müssen. Strings werden als URLs behandelt und in Request Sek. über new Request(theString).

Sie können Dinge von anderen Ursprüngen abrufen, solange die Ressourcen dies zulassen über CORS

Hinweis:Chrome unterstützt derzeit keine Anfragen, die ist ein CORS-Preflight erforderlich.

options Ein -Objekt, das Folgendes enthalten kann:
options.title string
Ein Titel, der dem Browser zusammen mit dem Fortschritt angezeigt werden soll.
options.icons Array<IconDefinition>
Ein Array von Objekten mit "src", "size" und "type".
options.downloadTotal number
Die Gesamtgröße der Antworttexte (nach dem Entpacken der GZIP-Datei).

Obwohl dies optional ist, wird dringend empfohlen, es anzugeben. Damit lassen sich wie groß der Download ist, und Informationen zum Fortschritt. Wenn Sie keine teilt der Browser dem Nutzer mit, dass die Größe unbekannt ist, sodass der Nutzer der Download wird wahrscheinlich abgebrochen.

Wenn die Downloads im Hintergrund den hier angegebenen Wert überschreiten, wird der Download abgebrochen. Es ist völlig in Ordnung, wenn der Download kleiner ist als downloadTotal. Wenn Sie also wie hoch die Downloadsumme ist, sollten Sie im Zweifelsfall Vorsicht walten lassen.

backgroundFetch.fetch gibt ein Promise zurück, das mit einem BackgroundFetchRegistration aufgelöst wird. Ich werde später darauf eingehen. Das Promise wird abgelehnt, wenn der Nutzer Downloads deaktiviert hat oder der angegebenen Parameter ist ungültig.

Wenn Sie viele Anfragen für einen einzelnen Hintergrundabruf bereitstellen, können Sie Dinge kombinieren, für die Nutzenden ist. Ein Film kann beispielsweise in Hunderte von Ressourcen aufgeteilt werden (üblicherweise mit MPEG-DASH), und zusätzliche Ressourcen wie Bilder zur Verfügung stellen. Ein Level eines Spiels kann über viele JavaScript-, Bild- und Audioressourcen Für den Nutzer ist es nur „der Film“ oder „das Level“.

Vorhandenen Hintergrundabruf abrufen

Sie können einen vorhandenen Hintergrundabruf wie folgt abrufen:

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});

Dabei wird die id des gewünschten Hintergrundabrufs übergeben. get gibt undefined zurück, wenn keine im Hintergrund mit dieser ID aktiv sein.

Ein Abruf im Hintergrund wird als „aktiv“ betrachtet von der Registrierung bis zum Erfolg. schlägt fehl oder wird abgebrochen.

Mit getIds können Sie eine Liste aller aktiven Hintergrundabrufe abrufen:

navigator.serviceWorker.ready.then(async (swReg) => {
  const ids = await swReg.backgroundFetch.getIds();
});

Registrierungen für Hintergrundabrufe

Ein BackgroundFetchRegistration (bgFetch in den Beispielen oben) hat Folgendes:

Attribute
id string
ID des Hintergrundabrufs.
uploadTotal number
Die Anzahl der Byte, die an den Server gesendet werden sollen.
uploaded number
Die Anzahl der erfolgreich gesendeten Byte.
downloadTotal number
Der Wert, der angegeben wurde, als der Hintergrundabruf registriert wurde, oder Null.
downloaded number
Die Anzahl der erfolgreich empfangenen Byte.

Dieser Wert kann sich verringern. Das ist beispielsweise der Fall, wenn die Verbindung unterbrochen wird und der Download nicht wird fortgesetzt. In diesem Fall startet der Browser den Abruf für diese Ressource von Grund auf neu.

result

Eines der folgenden Betriebssysteme:

  • "": Der Hintergrundabruf ist aktiv, daher liegt noch kein Ergebnis vor.
  • "success": Der Hintergrundabruf war erfolgreich.
  • "failure": Der Hintergrundabruf ist fehlgeschlagen. Dieser Wert erscheint nur, wenn schlägt der Hintergrundabruf fehl, da der Browser den Vorgang nicht wiederholen/fortsetzen kann.
failureReason

Eines der folgenden Betriebssysteme:

  • "": Der Abruf im Hintergrund ist nicht fehlgeschlagen.
  • "aborted": Der Hintergrundabruf wurde vom Nutzer abgebrochen. abort() wurde angerufen.
  • "bad-status": Eine der Antworten hatte den Status „Nicht in Ordnung“, z.B. 404.
  • "fetch-error": Einer der Abrufe ist aus einem anderen Grund fehlgeschlagen, z.B. CORS, MIX, eine ungültige Teilantwort oder ein allgemeiner Netzwerkfehler für einen Abruf, kann nicht wiederholt werden.
  • "quota-exceeded": Das Speicherkontingent wurde im Hintergrund erreicht Fetch".
  • "download-total-exceeded": Der angegebene `downloadTotal` betrug überschritten.
recordsAvailable boolean
Kann auf die zugrunde liegenden Anfragen/Antworten zugegriffen werden?

Wenn dieser Wert falsch ist, können match und matchAll nicht mehr verwendet werden.

Methoden
abort() Gibt Folgendes zurück: Promise<boolean>
Braucht den Hintergrundabruf ab.

Das zurückgegebene Promise wird mit „true“ aufgelöst, wenn der Abruf erfolgreich abgebrochen wurde.

matchAll(request, opts) Gibt Promise<Array<BackgroundFetchRecord>> zurück.
Anfragen abrufen und Antworten.

Die Argumente sind die gleichen wie Cache API hinzu. Beim Aufrufen ohne Argumente wird für alle Datensätze ein Promise zurückgegeben.

Weitere Details finden Sie unten.

match(request, opts) Gibt Promise<BackgroundFetchRecord>
Wie oben zurück, wird jedoch aufgelöst mit auf die erste Übereinstimmung.
Ereignisse
progress Wird ausgelöst, wenn uploaded, downloaded, result oder Änderung um failureReason.

Fortschritt wird erfasst

Dies ist über das Ereignis progress möglich. downloadTotal ist der Wert, den Sie oder 0, wenn Sie keinen Wert angegeben haben.

bgFetch.addEventListener('progress', () => {
  // If we didn't provide a total, we can't provide a %.
  if (!bgFetch.downloadTotal) return;

  const percent = Math.round(bgFetch.downloaded / bgFetch.downloadTotal * 100);
  console.log(`Download progress: ${percent}%`);
});

Anfragen und Antworten abrufen

bgFetch.match('/ep-5.mp3').then(async (record) => {
  if (!record) {
    console.log('No record found');
    return;
  }

  console.log(`Here's the request`, record.request);
  const response = await record.responseReady;
  console.log(`And here's the response`, response);
});

record ist eine BackgroundFetchRecord und sieht so aus:

Attribute
request Request
Die Anfrage, die gestellt wurde.
responseReady Promise<Response>
Die abgerufene Antwort.

Die Antwort liegt hinter einem Versprechen zurück, da es möglicherweise noch nicht eingegangen ist. Das Versprechen wird abgelehnt, wenn der Abruf fehlschlägt.

Service Worker-Ereignisse

Ereignisse
backgroundfetchsuccess Alles wurde abgerufen.
backgroundfetchfailure Mindestens ein Abruf ist fehlgeschlagen.
backgroundfetchabort Mindestens ein Abruf ist fehlgeschlagen.

Dies ist nur dann wirklich nützlich, wenn Sie verwandte Daten bereinigen möchten.

backgroundfetchclick Der Nutzer hat auf die Benutzeroberfläche für den Downloadfortschritt geklickt.

Die Ereignisobjekte haben Folgendes:

Attribute
registration BackgroundFetchRegistration
Methoden
updateUI({ title, icons }) Hier können Sie den ursprünglich festgelegten Titel und die Symbole ändern. Dies ist optional, bei Bedarf mehr Kontext liefern. Diese Aktion ist während des folgenden Zeitraums nur *einmal* möglich. backgroundfetchsuccess- und backgroundfetchfailure-Ereignisse.

Auf Erfolg/Misserfolg reagieren

Wir haben das progress-Ereignis bereits gesehen, aber dieses ist nur nützlich, wenn der Nutzer eine Seite geöffnet hat, für Ihre Website. Der Hauptvorteil des Abrufs im Hintergrund besteht darin, dass alles weiterhin funktioniert, nachdem der Nutzer die oder schließt den Browser sogar.

Wenn der Hintergrundabruf erfolgreich abgeschlossen wurde, empfängt Ihr Service Worker die backgroundfetchsuccess-Ereignis und event.registration ist die Registrierung für den Hintergrundabruf.

Nach diesem Ereignis sind die abgerufenen Anfragen und Antworten nicht mehr verfügbar. Wenn Sie sie behalten und an einen anderen Ort wie die Cache API verschieben.

Wie bei den meisten Service Worker-Ereignissen verwenden Sie event.waitUntil, damit der Service Worker weiß, wann das Ereignis abgeschlossen ist.

Zum Beispiel in Ihrem Service Worker:

addEventListener('backgroundfetchsuccess', (event) => {
  const bgFetch = event.registration;

  event.waitUntil(async function() {
    // Create/open a cache.
    const cache = await caches.open('downloads');
    // Get all the records.
    const records = await bgFetch.matchAll();
    // Copy each request/response across.
    const promises = records.map(async (record) => {
      const response = await record.responseReady;
      await cache.put(record.request, response);
    });

    // Wait for the copying to complete.
    await Promise.all(promises);

    // Update the progress notification.
    event.updateUI({ title: 'Episode 5 ready to listen!' });
  }());
});

Fehler können auf einen einzelnen 404-Fehler zurückzuführen sein, der für Sie nicht wichtig war. lohnt es sich dennoch, einige Antworten wie oben in einen Cache zu kopieren.

Auf Klick reagieren

Die Benutzeroberfläche, die den Downloadfortschritt und das Ergebnis anzeigt, ist anklickbar. Das backgroundfetchclick-Ereignis in können Sie mit dem Service Worker darauf reagieren. Wie oben ist event.registration der Hintergrund. Registrierung abrufen.

Häufig wird bei diesem Termin ein Fenster geöffnet:

addEventListener('backgroundfetchclick', (event) => {
  const bgFetch = event.registration;

  if (bgFetch.result === 'success') {
    clients.openWindow('/latest-podcasts');
  } else {
    clients.openWindow('/download-progress');
  }
});

Zusätzliche Ressourcen

Korrektur: In einer früheren Version dieses Artikels wurde der Hintergrundabruf fälschlicherweise als Webstandard bezeichnet. Die API befindet sich derzeit nicht in der Kategorie „Standards“. Die Spezifikation finden Sie im WICG als Entwurf für einen Community-Gruppenbericht.