2015 haben wir die Hintergrundsynchronisierung eingeführt. Damit kann der Service Worker Aufgaben aufschieben, bis der Nutzer wieder eine Verbindung hat. Das bedeutet, dass der Nutzer eine Nachricht eingeben und auf „Senden“ klicken kann. Dann kann er die Website verlassen und weiß, dass die Nachricht entweder jetzt gesendet wird oder sobald eine Verbindung besteht.
Dies ist ein nützliches Feature, setzt jedoch voraus, dass der Service Worker für die Dauer des Abrufs aktiv ist. Für kurze Arbeitsschritte wie das Senden einer Nachricht ist dies kein Problem. Wenn die Aufgabe jedoch zu lange dauert, beendet der Browser den Service Worker. Andernfalls besteht ein Risiko für den Datenschutz und den Akkuverbrauch des Nutzers.
Was ist also, wenn Sie etwas herunterladen möchten, das viel Zeit in Anspruch nimmt, wie einen Film, Podcasts oder bestimmte Level eines Spiels? Dazu dient Hintergrundabruf.
Seit Chrome 74 ist die Funktion „Hintergrundabruf“ standardmäßig verfügbar.
Hier ist eine kurze zweiminütige Demo, die den herkömmlichen Zustand der Vorgänge im Vergleich zur Verwendung von Hintergrundabruf zeigt:
Probiere die Demo selbst aus und sieh dir den Code an.
Funktionsweise
Ein Hintergrundabruf funktioniert so:
- Sie weisen den Browser an, im Hintergrund eine Gruppe von Abrufen auszuführen.
- Der Browser ruft diese Elemente ab und zeigt dem Nutzer den Fortschritt an.
- Sobald der Abruf abgeschlossen ist oder fehlgeschlagen ist, öffnet der Browser den Service Worker und löst ein Ereignis aus, um Sie darüber zu informieren, 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, ist das in Ordnung und der Download wird fortgesetzt. Da der Abruf gut sichtbar ist und einfach abgebrochen werden kann, ergibt sich aus Datenschutzgründen keine viel zu lange Hintergrundsynchronisierungsaufgabe. Da der Service Worker nicht ständig ausgeführt wird, besteht keine Gefahr, dass er das System missbrauchen könnte, z. B. wenn er im Hintergrund Bitcoin abbaut.
Auf einigen Plattformen (wie Android) kann der Browser nach Schritt 1 geschlossen werden, da der Browser den Abruf an das Betriebssystem übergeben kann.
Wenn der Nutzer den Download offline startet oder während des Downloads offline geht, wird der Hintergrundabruf pausiert und später fortgesetzt.
Mit der API
Featureerkennung
Wie bei jeder neuen Funktion möchten Sie herausfinden, ob der Browser diese Funktion unterstützt. Für Background Fetch ist das so einfach:
if ('BackgroundFetchManager' in self) {
// This browser supports Background Fetch!
}
Hintergrundabruf starten
Die Haupt-API hängt von einer Service Worker-Registrierung ab. Achten Sie daher darauf, dass Sie zuerst 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 Dieser Hintergrundabruf wird eindeutig identifiziert.
|
requests |
Array<Request|string>
Die abzurufenden Elemente. Strings werden als URLs behandelt und über new Request(theString) in Request -Werte umgewandelt.
Sie können Inhalte aus anderen Quellen abrufen, solange 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 zusammen mit dem Fortschritt im Browser 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 Entpacken mit gzip). Obwohl dies optional ist, wird dringend empfohlen, sie anzugeben. Sie wird verwendet, um dem Nutzer mitzuteilen, wie groß der Download ist, und um Informationen zum Fortschritt bereitzustellen. Wenn Sie dies nicht angeben, teilt der Browser dem Nutzer mit, dass die Größe unbekannt ist, und bricht den Download dann eher ab. Falls der Hintergrundabruf die hier angegebene Anzahl überschreitet, wird er abgebrochen. Es ist völlig in Ordnung, wenn der Download kleiner als |
backgroundFetch.fetch
gibt ein Versprechen zurück, das mit BackgroundFetchRegistration
aufgelöst wird. Darauf werde ich
später näher eingehen. Das Promise wird abgelehnt, wenn der Nutzer Downloads deaktiviert hat oder einer der angegebenen Parameter ungültig ist.
Durch die Bereitstellung vieler Anfragen für einen einzelnen Hintergrundabruf können Sie Dinge kombinieren, die für den Nutzer logisch einzigartig sind. Ein Film kann beispielsweise in Hunderte von Ressourcen aufgeteilt werden (üblich für MPEG-DASH) und zusätzliche Ressourcen wie Bilder enthalten. Ein Level eines Spiels kann über viele JavaScript-, Bild- und Audioressourcen verteilt sein. Für die Nutzenden ist es jedoch 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 kein aktiver Hintergrundabruf mit dieser ID vorhanden ist.
Ein Hintergrundabruf gilt ab der Registrierung als "aktiv", 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 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. Wenn beispielsweise die Verbindung unterbrochen wird und der Download nicht fortgesetzt werden kann, startet der Browser den Abruf für diese Ressource von Grund auf neu. |
result |
Eines der folgenden Betriebssysteme:
|
failureReason |
Eines der folgenden Betriebssysteme:
|
recordsAvailable |
boolean Kann ich auf die zugrunde liegenden Anfragen/Antworten zugreifen? Ist dieser Wert falsch, kann |
Methoden | |
abort() |
Gibt Folgendes zurück: Promise<boolean> Hintergrundabruf abbrechen. Das zurückgegebene Versprechen 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 hier sind mit denen der Cache API identisch. Ein Aufruf ohne Argumente gibt ein Promise für alle Datensätze zurück. Weitere Details finden Sie unten. |
match(request, opts) |
Gibt Promise<BackgroundFetchRecord> Wie oben zurück, wird aber mit der ersten Übereinstimmung aufgelöst. |
Veranstaltungen | |
progress |
Wird ausgelöst, wenn sich uploaded , downloaded , result oder failureReason ändern. |
Fortschritt wird erfasst
Dies kann über das Ereignis progress
erfolgen. Denken Sie daran, dass downloadTotal
der von Ihnen angegebene Wert ist 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 Anfrage, die gestellt wurde. |
responseReady |
Promise<Response> Die abgerufene Antwort. Die Antwort liegt hinter einem Versprechen, weil sie möglicherweise noch nicht erhalten wurde. Das Promise wird abgelehnt, wenn der Abruf fehlschlägt. |
Service Worker-Ereignisse
Veranstaltungen | |
---|---|
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 Titel und die Symbole ändern, die Sie anfangs festgelegt haben. Dies ist optional, ermöglicht aber bei Bedarf mehr Kontext. Dies ist nur *einmal* während der Ereignisse backgroundfetchsuccess und backgroundfetchfailure möglich. |
Auf Erfolg/Missfolge reagieren
Wir haben das Ereignis progress
bereits gesehen, aber es ist nur sinnvoll, wenn der Nutzer eine Seite für deine Website geöffnet hat. Der Hauptvorteil des Hintergrundabrufs besteht darin, dass die Seite weiterhin funktioniert, nachdem der Nutzer die Seite verlassen oder sogar den Browser geschlossen hat.
Wenn der Hintergrundabruf erfolgreich abgeschlossen wurde, empfängt Ihr Service Worker das Ereignis backgroundfetchsuccess
und event.registration
ist die Registrierung für den Hintergrundabruf.
Nach diesem Ereignis ist der Zugriff auf die abgerufenen Anfragen und Antworten nicht mehr möglich. Wenn Sie sie also behalten möchten, verschieben Sie sie an einen anderen Ort wie die Cache API.
Verwenden Sie wie bei den meisten Service Worker-Ereignissen 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!' });
}());
});
Der Fehler kann auf einen einzelnen 404-Fehler zurückzuführen sein, was für Sie möglicherweise nicht wichtig war. Daher kann es sich lohnen, einige Antworten wie oben in einen Cache zu kopieren.
Auf Klicks reagieren
Auf der Benutzeroberfläche werden der Downloadfortschritt und das Ergebnis angezeigt. Mit dem Ereignis backgroundfetchclick
im Service Worker können Sie darauf reagieren. Wie oben ist event.registration
die Registrierung für den Hintergrundabruf.
Bei diesem Ereignis müssen Sie häufig ein Fenster öffnen:
addEventListener('backgroundfetchclick', (event) => {
const bgFetch = event.registration;
if (bgFetch.result === 'success') {
clients.openWindow('/latest-podcasts');
} else {
clients.openWindow('/download-progress');
}
});
Weitere Ressourcen
Korrektur: In einer früheren Version dieses Artikels wurde Hintergrundabruf fälschlicherweise als „Webstandard“ bezeichnet. Die API befindet sich derzeit nicht im Standard-Track. Die Spezifikation finden Sie in der WICG als Entwurf für einen Community Group-Bericht.