In 2015 introduceerden we Achtergrondsynchronisatie , waarmee de servicemedewerker werk kan uitstellen totdat de gebruiker weer verbinding heeft. Dit betekent dat de gebruiker een bericht kan typen, op verzenden kan klikken en de site kan verlaten, wetende dat het bericht nu wordt verzonden of zodra de gebruiker weer verbinding heeft.
Het is een handige functie, maar vereist wel dat de service worker actief blijft gedurende de hele ophaalactie. Dat is geen probleem voor korte taken zoals het versturen van een bericht, maar als de taak te lang duurt, sluit de browser de service worker af, anders loopt de privacy en batterij van de gebruiker gevaar.
Dus, wat als je iets moet downloaden dat lang kan duren, zoals een film, podcasts of levels van een game? Daar is Background Fetch voor.
Achtergrond ophalen is standaard beschikbaar sinds Chrome 74.
Hier is een korte demo van twee minuten die de traditionele stand van zaken laat zien, vergeleken met het gebruik van Background Fetch:
Hoe het werkt
Het ophalen van de achtergrond werkt als volgt:
- U vertelt de browser dat deze op de achtergrond een aantal ophaalacties moet uitvoeren.
- De browser haalt deze gegevens op en toont de voortgang aan de gebruiker.
- Zodra het ophalen is voltooid of mislukt, opent de browser uw service worker en genereert een gebeurtenis om u te laten weten wat er is gebeurd. Hier bepaalt u wat er eventueel met de reacties moet gebeuren.
Als de gebruiker na stap 1 pagina's van je site sluit, is dat geen probleem; de download gaat gewoon door. Omdat de fetch goed zichtbaar is en gemakkelijk kan worden afgebroken, is er geen sprake van privacyproblemen door een te lange synchronisatietaak op de achtergrond. Omdat de service worker niet constant draait, is er geen risico dat deze het systeem zou kunnen misbruiken, zoals bitcoinmining op de achtergrond.
Op sommige platforms (zoals Android) kan het voorkomen dat de browser na stap 1 sluit, omdat de browser het ophalen aan het besturingssysteem kan overdragen.
Als de gebruiker het downloaden start terwijl hij/zij offline is, of offline gaat tijdens het downloaden, wordt het ophalen op de achtergrond gepauzeerd en later hervat.
De API
Functiedetectie
Zoals met elke nieuwe functie wilt u controleren of de browser deze ondersteunt. Voor het ophalen op de achtergrond is het zo eenvoudig als:
if ('BackgroundFetchManager' in self) {
// This browser supports Background Fetch!
}
Een achtergrondophaling starten
De belangrijkste API is afhankelijk van de registratie van een service worker , dus zorg ervoor dat u eerst een service worker hebt geregistreerd. Vervolgens:
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:
Parameters | |
---|---|
id | string Identificeert deze achtergrondophaling op unieke wijze. |
requests | Array< Request |string> De op te halen items. Strings worden behandeld als URL's en omgezet in Request via new Request(theString) .Je kunt dingen ophalen van andere bronnen, zolang de bronnen dit toelaten via CORS . Let op: Chrome ondersteunt momenteel geen verzoeken waarvoor een CORS-preflight nodig is. |
options | Een object dat het volgende kan omvatten: |
options.title | string Een titel die de browser samen met de voortgang weergeeft. |
options.icons | Array< IconDefinition > Een reeks 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 het sterk aanbevolen om het wel te vermelden. Het wordt gebruikt om de gebruiker te informeren over de grootte van de download en om informatie over de voortgang te verstrekken. Als u dit niet doet, zal de browser de gebruiker laten weten dat de grootte onbekend is, waardoor de kans groter is dat de gebruiker de download afbreekt. Als het aantal downloads op de achtergrond het hier opgegeven aantal overschrijdt, wordt de download afgebroken. Het is prima als de download kleiner is dan de |
backgroundFetch.fetch
retourneert een promise die resulteert in een BackgroundFetchRegistration
. Ik zal later meer details hierover bespreken. De promise wordt afgewezen als de gebruiker zich heeft afgemeld voor downloads, of als een van de opgegeven parameters ongeldig is.
Door meerdere verzoeken voor één achtergrondophaling in te dienen, kun je dingen combineren die voor de gebruiker logischerwijs één ding zijn. Een film kan bijvoorbeeld worden opgedeeld in duizenden bronnen (typisch met MPEG-DASH ) en worden geleverd met extra bronnen zoals afbeeldingen. Een level van een game kan verspreid zijn over meerdere JavaScript-, afbeeldings- en audiobronnen. Maar voor de gebruiker is het gewoon "de film" of "het level".
Een bestaande achtergrond ophalen
U kunt een bestaande achtergrond als volgt ophalen:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});
…door de id van de gewenste achtergrondophaling door te geven. get
retourneert undefined
als er geen actieve achtergrondophaling is met die ID.
Een achtergrondophaling wordt als 'actief' beschouwd vanaf het moment dat deze wordt geregistreerd, totdat deze slaagt, mislukt of wordt afgebroken.
Met getIds
kunt u een lijst met alle actieve achtergrondophalingen verkrijgen:
navigator.serviceWorker.ready.then(async (swReg) => {
const ids = await swReg.backgroundFetch.getIds();
});
Achtergrondophaalregistraties
Een BackgroundFetchRegistration
( bgFetch
in de bovenstaande voorbeelden) heeft het volgende:
Eigenschappen | |
---|---|
id | string De ID van de achtergrondophaling. |
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 is opgegeven bij het registreren van het ophalen van de achtergrond, of nul. |
downloaded | number Het aantal bytes dat succesvol is ontvangen. Deze waarde kan dalen. Bijvoorbeeld, als de verbinding wegvalt en de download niet kan worden hervat, start de browser het ophalen van die bron opnieuw. |
result | Een van de volgende:
|
failureReason | Een van de volgende:
|
recordsAvailable | boolean Zijn de onderliggende verzoeken/reacties toegankelijk? Als dit onwaar is, kunnen |
Methoden | |
abort() | Retourneert Promise<boolean> Het ophalen van de achtergrond annuleren. De geretourneerde belofte wordt opgelost met true als het ophalen succesvol is afgebroken. |
matchAll(request, opts) | Retourneert Promise<Array<BackgroundFetchRecord>> Ontvang de verzoeken en reacties. De argumenten hier zijn hetzelfde als die van de cache-API . Aanroepen zonder argumenten retourneert een promise voor alle records. Zie hieronder voor meer details. |
match(request, opts) | Retourneert Promise<BackgroundFetchRecord> Zoals hierboven, maar opgelost met de eerste match. |
Evenementen | |
progress | Wordt geactiveerd wanneer een van de volgende variabelen verandert: uploaded , downloaded , result failureReason . |
Voortgang volgen
Dit kan via de progress
. Onthoud dat downloadTotal
de waarde is die u hebt opgegeven, of 0
als u geen waarde hebt 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 reacties
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 zo uit:
Eigenschappen | |
---|---|
request | Request Het verzoek dat werd gedaan. |
responseReady | Promise<Response> Het opgehaalde antwoord. Het antwoord staat achter een belofte, omdat het mogelijk nog niet is ontvangen. De belofte wordt afgewezen als het ophalen mislukt. |
Evenementen voor servicemedewerkers
Evenementen | |
---|---|
backgroundfetchsuccess | Alles is succesvol opgehaald. |
backgroundfetchfailure | Eén of meer ophaalacties zijn mislukt. |
backgroundfetchabort | Eén of meer ophaalacties zijn mislukt. Dit is alleen echt nuttig als u opschoning van gerelateerde gegevens wilt uitvoeren. |
backgroundfetchclick | De gebruiker heeft op de gebruikersinterface voor de downloadvoortgang geklikt. |
De gebeurtenisobjecten hebben het volgende:
Eigenschappen | |
---|---|
registration | BackgroundFetchRegistration |
Methoden | |
updateUI({ title, icons }) | Hiermee kunt u de titel/pictogrammen die u oorspronkelijk hebt ingesteld, wijzigen. Dit is optioneel, maar het geeft u de mogelijkheid om indien nodig meer context te bieden. U kunt dit *slechts* doen tijdens de gebeurtenissen backgroundfetchsuccess en backgroundfetchfailure . |
Reageren op succes/falen
We hebben de progress
al gezien, maar die is alleen nuttig zolang de gebruiker een pagina op je site open heeft staan. Het belangrijkste voordeel van ophalen op de achtergrond is dat alles blijft werken nadat de gebruiker de pagina verlaat of zelfs de browser sluit.
Als het ophalen van de achtergrond succesvol wordt voltooid, ontvangt uw service worker de gebeurtenis backgroundfetchsuccess
en wordt event.registration
de registratie voor het ophalen van de achtergrond.
Na deze gebeurtenis zijn de opgehaalde verzoeken en antwoorden niet meer toegankelijk. Als u ze wilt bewaren, verplaatst u ze naar een locatie, bijvoorbeeld de cache-API .
Zoals bij de meeste service worker-gebeurtenissen gebruikt u event.waitUntil
, zodat de service worker weet wanneer de gebeurtenis is voltooid.
Bijvoorbeeld in uw servicemedewerker:
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 kan zijn dat de foutmelding slechts één 404 is, wat voor u niet van belang is. In dat geval kan het de moeite waard zijn om een aantal reacties naar een cache te kopiëren, zoals hierboven beschreven.
Reageren op klikken
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 beschreven, zal event.registration
de registratie op de achtergrond zijn.
Het gebruikelijke wat je bij deze gebeurtenis doet, 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 aangeduid als een "webstandaard". De API is momenteel niet op het standaardisatiepad; de specificatie is te vinden in WICG als een concept Community Group Report.