In 2015 hebben we Achtergrondsynchronisatie geïntroduceerd , waarmee de servicemedewerker zijn werk kan uitstellen totdat de gebruiker verbinding heeft. Dit betekent dat de gebruiker een bericht kan typen, op verzenden kan drukken en de site kan verlaten in de wetenschap dat het bericht nu zal worden verzonden of wanneer er verbinding is.
Het is een nuttige functie, maar het vereist dat de servicemedewerker in leven blijft tijdens de duur van het ophalen. Dat is geen probleem voor korte stukjes werk, zoals het verzenden van een bericht, maar als de taak te lang duurt, zal de browser de servicemedewerker doden, anders is het een risico voor de privacy en de batterij van de gebruiker.
Dus wat als u iets moet downloaden dat lang kan duren, zoals een film, podcasts of niveaus van een game. Dat is waar Background Fetch voor is.
Background Fetch is standaard beschikbaar sinds Chrome 74.
Hier is een korte demo van twee minuten die de traditionele stand van zaken laat zien, versus het gebruik van Background Fetch:
Probeer de demo zelf en blader door de code .
Hoe het werkt
Een achtergrondophaalactie werkt als volgt:
- U vertelt de browser om een groep ophaalacties op de achtergrond uit te voeren.
- De browser haalt die dingen op en geeft de voortgang aan de gebruiker weer.
- Zodra het ophalen is voltooid of mislukt, opent de browser uw servicemedewerker en activeert een gebeurtenis om u te vertellen wat er is gebeurd. Hier beslist u wat u eventueel met de reacties doet.
Als de gebruiker na stap 1 pagina's op uw site sluit, is dat geen probleem. De download gaat door. Omdat het ophalen goed zichtbaar is en gemakkelijk kan worden afgebroken, is er geen sprake van privacyproblemen door een veel te lange synchronisatietaak op de achtergrond. Omdat de servicemedewerker niet voortdurend aan het werk is, bestaat er geen angst dat hij het systeem zou kunnen misbruiken, zoals het minen van bitcoin op de achtergrond.
Op sommige platforms (zoals Android) is het mogelijk dat de browser na stap 1 sluit, omdat de browser het ophalen aan het besturingssysteem kan overdragen.
Als de gebruiker de download start terwijl hij offline is, of offline gaat tijdens de download, wordt het ophalen op de achtergrond gepauzeerd en later hervat.
De API
Functie detecteren
Zoals bij elke nieuwe functie wilt u detecteren of de browser deze ondersteunt. Voor Background Fetch is het zo simpel als:
if ('BackgroundFetchManager' in self) {
// This browser supports Background Fetch!
}
Een achtergrondophaalactie starten
De hoofd-API blokkeert de registratie van een servicemedewerker , dus zorg ervoor dat u eerst een servicemedewerker heeft geregistreerd. Dan:
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
heeft drie argumenten nodig:
Parameters | |
---|---|
id | string identificeert op unieke wijze deze achtergrondophaalactie. |
requests | Array< Request |string> De dingen die je moet halen. Tekenreeksen worden behandeld als URL's en omgezet in Request via new Request(theString) .Je kunt dingen van andere oorsprong ophalen, zolang de bronnen dit toestaan via CORS . Opmerking: Chrome ondersteunt momenteel geen verzoeken waarvoor een CORS-preflight vereist is. |
options | Een object dat het volgende kan bevatten: |
options.title | string Een titel die de browser samen met de voortgang kan weergeven. |
options.icons | Array< IconDefinition > Een array van objecten met een `src`, `size` en `type`. |
options.downloadTotal | number De totale grootte van de antwoordteksten (nadat ze zijn uitgepakt). Hoewel dit optioneel is, wordt u ten zeerste aanbevolen dit op te geven. Het wordt gebruikt om de gebruiker te vertellen hoe groot de download is en om voortgangsinformatie te geven. Als u dit niet opgeeft, zal de browser de gebruiker vertellen dat de grootte onbekend is, waardoor de kans groter is dat de gebruiker de download afbreekt. Als het aantal ophaaldownloads op de achtergrond het hier opgegeven aantal overschrijdt, wordt dit afgebroken. Het is prima als de download kleiner is dan de |
backgroundFetch.fetch
retourneert een belofte die wordt opgelost met een BackgroundFetchRegistration
. Ik zal de details daarvan later bespreken. De belofte wordt afgewezen als de gebruiker zich heeft afgemeld voor downloads of als een van de opgegeven parameters ongeldig is.
Door veel verzoeken voor een enkele ophaalactie op de achtergrond aan te bieden, kunt u dingen combineren die logischerwijs één ding zijn voor de gebruiker. Een film kan bijvoorbeeld worden opgesplitst in duizenden bronnen (typisch bij MPEG-DASH ) en worden geleverd met extra bronnen zoals afbeeldingen. Een niveau van een game kan over veel JavaScript-, beeld- en audiobronnen worden verspreid. Maar voor de gebruiker is het gewoon ‘de film’, of ‘het niveau’.
Een bestaande achtergrond ophalen
U kunt als volgt een bestaande achtergrond ophalen:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});
…door de id van de gewenste achtergrondophaalactie door te geven. get
rendement undefined
als er geen actieve achtergrondophaalactie is met die ID.
Een ophaalactie op de achtergrond wordt als 'actief' beschouwd vanaf het moment dat deze wordt geregistreerd, totdat deze slaagt, mislukt of wordt afgebroken.
Je kunt een lijst krijgen met alle actieve ophaalacties op de achtergrond met behulp van getIds
:
navigator.serviceWorker.ready.then(async (swReg) => {
const ids = await swReg.backgroundFetch.getIds();
});
Ophaalregistraties op de achtergrond
Een BackgroundFetchRegistration
( bgFetch
in de bovenstaande voorbeelden) heeft het volgende:
Eigenschappen | |
---|---|
id | string De ID van de achtergrondophaalactie. |
uploadTotal | number Het aantal bytes dat naar de server moet worden verzonden. |
uploaded | number Het aantal bytes dat succesvol is verzonden. |
downloadTotal | number De waarde die werd opgegeven toen het ophalen op de achtergrond werd geregistreerd, of nul. |
downloaded | number Het aantal succesvol ontvangen bytes. Deze waarde kan afnemen. Als de verbinding bijvoorbeeld wegvalt en het downloaden niet kan worden hervat, in welk geval de browser het ophalen van die bron helemaal opnieuw start. |
result | Een van de volgende:
|
failureReason | Een van de volgende:
|
recordsAvailable | boolean Zijn de onderliggende verzoeken/antwoorden toegankelijk? Zodra dit false is, kan |
Methoden | |
abort() | Retourneert Promise<boolean> Breek het ophalen van de achtergrond af. De geretourneerde belofte wordt opgelost met true als het ophalen met succes is afgebroken. |
matchAll(request, opts) | Retourneert Promise<Array<BackgroundFetchRecord>> Ontvang de verzoeken en antwoorden. De argumenten hier zijn hetzelfde als die van de cache-API . Bellen zonder argumenten levert een belofte op voor alle records. Zie hieronder voor meer details. |
match(request, opts) | Retourneert Promise<BackgroundFetchRecord> Zoals hierboven, maar opgelost bij de eerste wedstrijd. |
Evenementen | |
progress | Wordt geactiveerd wanneer een van de uploaded , downloaded , result of failureReason wijzigingen plaatsvindt. |
Het bijhouden van de voortgang
Dit kan via het progress
. Houd er rekening mee dat downloadTotal
de waarde is die u heeft opgegeven, of 0
als u geen waarde heeft opgegeven.
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}%`);
});
Het ontvangen van de verzoeken en antwoorden
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
is een BackgroundFetchRecord
en ziet er als volgt uit:
Eigenschappen | |
---|---|
request | Request Het verzoek dat is ingediend. |
responseReady | Promise<Response> Het opgehaalde antwoord. Het antwoord zit achter een belofte omdat deze mogelijk nog niet is ontvangen. De belofte wordt afgewezen als het ophalen mislukt. |
Evenementen voor servicemedewerkers
Evenementen | |
---|---|
backgroundfetchsuccess | Alles is succesvol opgehaald. |
backgroundfetchfailure | Een of meer ophaalbewerkingen zijn mislukt. |
backgroundfetchabort | Een of meer ophaalbewerkingen zijn mislukt. Dit is alleen echt handig als u gerelateerde gegevens wilt opschonen. |
backgroundfetchclick | De gebruiker klikte op de downloadvoortgangsinterface. |
De gebeurtenisobjecten hebben het volgende:
Eigenschappen | |
---|---|
registration | BackgroundFetchRegistration |
Methoden | |
updateUI({ title, icons }) | Hiermee kunt u de titel/pictogrammen wijzigen die u aanvankelijk hebt ingesteld. Dit is optioneel, maar hiermee kunt u indien nodig meer context bieden. U kunt dit slechts *eenmaal* doen tijdens de gebeurtenissen backgroundfetchsuccess en backgroundfetchfailure . |
Reageren op succes/mislukking
We hebben de progress
al gezien, maar dat is alleen nuttig als de gebruiker een pagina op uw site heeft geopend. Het belangrijkste voordeel van ophalen op de achtergrond is dat alles blijft werken nadat de gebruiker de pagina heeft verlaten of zelfs de browser heeft gesloten.
Als het ophalen op de achtergrond succesvol is voltooid, ontvangt uw servicemedewerker de gebeurtenis backgroundfetchsuccess
en is event.registration
de registratie voor het ophalen op de achtergrond.
Na deze gebeurtenis zijn de opgehaalde verzoeken en antwoorden niet langer toegankelijk, dus als u ze wilt behouden, verplaats ze dan ergens naar de cache-API .
Zoals bij de meeste servicemedewerkergebeurtenissen gebruikt u event.waitUntil
zodat de servicemedewerker weet wanneer de gebeurtenis is voltooid.
In uw servicemedewerker bijvoorbeeld:
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!' });
}());
});
Het mislukken kan te maken hebben met één enkele 404, wat misschien niet belangrijk voor u was, dus het kan toch de moeite waard zijn om enkele reacties naar een cache te kopiëren, zoals hierboven.
Reageren op klik
De gebruikersinterface die de downloadvoortgang en het resultaat weergeeft, is klikbaar. Met de gebeurtenis backgroundfetchclick
in de service worker kunt u hierop reageren. Zoals hierboven zal event.registration
de ophaalregistratie op de achtergrond zijn.
Het gebruikelijke wat u met deze gebeurtenis kunt doen, is een venster openen:
addEventListener('backgroundfetchclick', (event) => {
const bgFetch = event.registration;
if (bgFetch.result === 'success') {
clients.openWindow('/latest-podcasts');
} else {
clients.openWindow('/download-progress');
}
});
Aanvullende bronnen
Correctie: in een eerdere versie van dit artikel werd Background Fetch ten onrechte een "webstandaard" genoemd. De API bevindt zich momenteel niet op het standaardspoor, de specificatie is te vinden in WICG als een concept-communitygroeprapport.