2015 haben wir die Hintergrundsynchronisierung eingeführt, mit der der Service Worker Aufgaben aufschieben kann, bis der Nutzer eine Verbindung hat. Das bedeutet, dass der Nutzer eine Nachricht eingeben, auf „Senden“ klicken und die Website verlassen kann, da die Nachricht entweder sofort oder bei bestehender Verbindung gesendet wird.
Das ist eine nützliche Funktion, aber der Service Worker muss für die Dauer des Abrufs aktiv sein. Bei kurzen Aufgaben wie dem Senden einer Nachricht ist das kein Problem. Wenn die Aufgabe jedoch zu lange dauert, beendet der Browser den Service Worker, da dies sonst ein Risiko für den Datenschutz und den Akku des Nutzers darstellt.
Was ist aber, wenn Sie etwas herunterladen müssen, das lange dauern kann, z. B. einen Film, Podcasts oder Level eines Spiels? Dafür gibt es den Hintergrundabruf.
Background Fetch ist seit Chrome 74 standardmäßig verfügbar.
In dieser kurzen zweiminütigen Demo sehen Sie, wie es bisher war und wie es mit Background Fetch ist:
Funktionsweise
So funktioniert ein Hintergrundabruf:
- Sie weisen den Browser an, eine Gruppe von Abrufen im Hintergrund auszuführen.
- Der Browser ruft diese Elemente ab und zeigt dem Nutzer den Fortschritt an.
- Sobald der Abruf abgeschlossen oder fehlgeschlagen ist, öffnet der Browser Ihren Service Worker und löst ein Ereignis aus, um Sie darüber zu informieren, was passiert ist. Hier entscheiden Sie, was mit den Antworten geschehen soll.
Wenn der Nutzer nach Schritt 1 Seiten Ihrer Website schließt, ist das in Ordnung. Der Download wird fortgesetzt. Da der Abruf gut sichtbar und leicht abzubrechen ist, besteht nicht das Datenschutzproblem einer viel zu langen Hintergrundsynchronisierungsaufgabe. Da der Service Worker nicht ständig ausgeführt wird, besteht nicht die Gefahr, dass er das System missbraucht, z. B. durch das Mining von Bitcoins im Hintergrund.
Auf einigen Plattformen (z. B. Android) kann es sein, dass der Browser nach Schritt 1 geschlossen wird, da er das Abrufen an das Betriebssystem übergeben kann.
Wenn der Nutzer den Download startet, während er offline ist, oder während des Downloads offline geht, wird der Hintergrundabruf pausiert und später fortgesetzt.
Mit der API
Funktionserkennung
Wie bei jeder neuen Funktion müssen Sie prüfen, ob der Browser sie unterstützt. Für den Hintergrundabruf ist es ganz einfach:
if ('BackgroundFetchManager' in self) {
// This browser supports Background Fetch!
}
Hintergrundabruf starten
Die Haupt-API hängt von einer Service Worker-Registrierung ab. Registrieren Sie also zuerst einen Service Worker. 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,
});
});
backgroundFetch.fetch
verwendet drei Argumente:
Parameter | |
---|---|
id |
string kennzeichnet diesen Hintergrundabruf eindeutig.
|
requests |
Array<Request|string>
Die abzurufenden Elemente. Strings werden als URLs behandelt und über new Request(theString) in Request s umgewandelt.
Sie können Inhalte aus anderen Ursprüngen abrufen, sofern die Ressourcen dies über CORS zulassen. Hinweis:Chrome unterstützt derzeit keine Anfragen, für die ein CORS-Preflight erforderlich wäre. |
options |
Ein Objekt, das Folgendes enthalten kann: |
options.title |
string Ein Titel, der im Browser zusammen mit dem Fortschritt angezeigt wird. |
options.icons |
Array<IconDefinition> Ein Array von Objekten mit „src“, „size“ und „type“. |
options.downloadTotal |
number Die Gesamtgröße der Antworttexte (nach dem Entzippen). Diese Angabe ist zwar optional, wird aber dringend empfohlen. Sie wird verwendet, um dem Nutzer die Größe des Downloads mitzuteilen und Fortschrittsinformationen bereitzustellen. Wenn Sie diese Angabe nicht machen, wird dem Nutzer im Browser angezeigt, dass die Größe unbekannt ist. Das kann dazu führen, dass der Nutzer den Download eher abbricht. Wenn die Anzahl der Downloads im Hintergrund die hier angegebene Zahl überschreitet, wird der Vorgang abgebrochen. Es ist in Ordnung, wenn der Download kleiner als |
backgroundFetch.fetch
gibt ein Promise zurück, das mit einem BackgroundFetchRegistration
aufgelöst wird. Die Details dazu werden später erläutert. Das Promise wird abgelehnt, wenn der Nutzer Downloads deaktiviert hat oder einer der angegebenen Parameter ungültig ist.
Wenn Sie viele Anfragen für einen einzelnen Hintergrundabruf bereitstellen, können Sie Dinge kombinieren, die für den Nutzer logisch zusammengehören. Ein Film kann beispielsweise in Tausende von Ressourcen aufgeteilt sein (typisch bei MPEG-DASH) und zusätzliche Ressourcen wie Bilder enthalten. Ein Level eines Spiels kann sich über viele JavaScript-, Bild- und Audioressourcen erstrecken. Für den Nutzer ist es aber einfach „der Film“ oder „das Level“.
Vorhandenen Hintergrundabruf abrufen
So können Sie einen vorhandenen Hintergrundabruf abrufen:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});
…indem Sie die id des gewünschten Hintergrundabrufs übergeben. get
gibt undefined
zurück, wenn kein aktiver Hintergrundabruf mit dieser ID vorhanden ist.
Ein Hintergrundabruf gilt als „aktiv“, sobald er registriert wird, bis er entweder erfolgreich ist, fehlschlägt oder abgebrochen wird.
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 den Hintergrundabruf
Ein BackgroundFetchRegistration
(bgFetch
in den obigen Beispielen) hat Folgendes:
Attribute | |
---|---|
id |
string Die ID des Hintergrundabrufs. |
uploadTotal |
number Die Anzahl der Bytes, die an den Server gesendet werden sollen. |
uploaded |
number Die Anzahl der erfolgreich gesendeten Byte. |
downloadTotal |
number Der Wert, der bei der Registrierung des Hintergrundabrufs angegeben wurde, oder null. |
downloaded |
number Die Anzahl der erfolgreich empfangenen Bytes. Dieser Wert kann sinken. Wenn beispielsweise die Verbindung unterbrochen wird und der Download nicht fortgesetzt werden kann, startet der Browser den Abruf für diese Ressource von vorn. |
result |
Eines der folgenden Betriebssysteme:
|
failureReason |
Eines der folgenden Betriebssysteme:
|
recordsAvailable |
boolean Kann auf die zugrunde liegenden Anfragen/Antworten zugegriffen werden? Wenn dieser Wert „false“ ist, können |
Methoden | |
abort() |
Gibt Promise<boolean> Hintergrundabruf abbrechen zurück. Das zurückgegebene Promise wird mit „true“ aufgelöst, wenn der Abruf erfolgreich abgebrochen wurde. |
matchAll(request, opts) |
Gibt Promise<Array<BackgroundFetchRecord>> zurück. Ruft die Anfragen und Antworten ab. Die Argumente sind dieselben wie bei der Cache API. Wenn Sie die Funktion ohne Argumente aufrufen, wird ein Promise für alle Datensätze zurückgegeben. Weitere Details finden Sie unten. |
match(request, opts) |
Gibt Promise<BackgroundFetchRecord> zurück. Wie oben, aber mit dem ersten Treffer. |
Ereignisse | |
progress |
Wird ausgelöst, wenn sich uploaded , downloaded , result oder failureReason ändern. |
Fortschritt verfolgen
Das ist über das Ereignis progress
möglich. downloadTotal
ist der von Ihnen angegebene Wert 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 ein BackgroundFetchRecord
und sieht so aus:
Attribute | |
---|---|
request |
Request Die bereitgestellte Anfrage. |
responseReady |
Promise<Response> Die abgerufene Antwort. Die Antwort ist hinter einem Promise, weil sie möglicherweise noch nicht empfangen wurde. Das Promise wird abgelehnt, wenn der Abruf fehlschlägt. |
Service Worker-Ereignisse
Ereignisse | |
---|---|
backgroundfetchsuccess |
Alle Daten wurden erfolgreich abgerufen. |
backgroundfetchfailure |
Mindestens einer der Abrufe ist fehlgeschlagen. |
backgroundfetchabort |
Mindestens ein Abruf ist fehlgeschlagen.
Das ist nur wirklich nützlich, wenn Sie zugehörige 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 Titel und die Symbole ändern, die Sie ursprünglich festgelegt haben. Das ist optional, aber so können Sie bei Bedarf mehr Kontext angeben. Sie können dies nur *einmal* während der Ereignisse backgroundfetchsuccess und backgroundfetchfailure tun. |
Auf Erfolg/Fehler reagieren
Wir haben das Ereignis progress
bereits gesehen, aber das ist nur nützlich, solange der Nutzer eine Seite Ihrer Website geöffnet hat. Der Hauptvorteil des Hintergrundabrufs besteht darin, dass die Dinge weiterhin funktionieren, nachdem der Nutzer die Seite verlassen oder den Browser sogar geschlossen hat.
Wenn der Hintergrundabruf erfolgreich abgeschlossen wurde, empfängt Ihr Service Worker das backgroundfetchsuccess
-Ereignis und event.registration
ist die Registrierung für den Hintergrundabruf.
Nach diesem Ereignis sind die abgerufenen Anfragen und Antworten nicht mehr zugänglich. Wenn Sie sie behalten möchten, verschieben Sie sie an einen anderen Ort, z. B. in die Cache API.
Wie bei den meisten Service Worker-Ereignissen sollten Sie event.waitUntil
verwenden, 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!' });
}());
});
Der Fehler kann auf einen einzelnen 404-Fehler zurückzuführen sein, der für Sie möglicherweise nicht wichtig war. Es kann sich also lohnen, einige Antworten wie oben in einen Cache zu kopieren.
Reaktion auf Klick
Die Benutzeroberfläche, auf der der Downloadfortschritt und das Ergebnis angezeigt werden, ist anklickbar. Mit dem backgroundfetchclick
-Ereignis im Service Worker können Sie darauf reagieren. Wie oben beschrieben ist event.registration
die Registrierung für das Abrufen im Hintergrund.
Die häufigste Aktion bei diesem Ereignis ist das Öffnen eines Fensters:
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 Background Fetch fälschlicherweise als „Webstandard“ bezeichnet. Die API befindet sich derzeit nicht auf dem Standard-Track. Die Spezifikation ist in WICG als Draft Community Group Report verfügbar.