W 2015 r. wprowadziliśmy synchronizację w tle, która umożliwia odroczenie pracy service workera do momentu, gdy użytkownik będzie mieć połączenie z internetem. Oznacza to, że użytkownik może wpisać wiadomość, kliknąć „Wyślij” i opuścić witrynę, wiedząc, że wiadomość zostanie wysłana od razu lub po uzyskaniu połączenia z internetem.
Jest to przydatna funkcja, ale wymaga, aby proces roboczy usługi był aktywny przez cały czas trwania pobierania. Nie stanowi to problemu w przypadku krótkich zadań, takich jak wysyłanie wiadomości, ale jeśli zadanie trwa zbyt długo, przeglądarka zakończy działanie service workera, ponieważ w przeciwnym razie stanowiłoby to zagrożenie dla prywatności użytkownika i baterii.
Co zrobić, jeśli chcesz pobrać coś, co może zająć dużo czasu, np. film, podcasty lub poziomy gry? Do tego służy pobieranie w tle.
Interfejs Background Fetch jest domyślnie dostępny od Chrome 74.
Oto 2-minutowa prezentacja pokazująca tradycyjny stan rzeczy w porównaniu z używaniem pobierania w tle:
Jak to działa
Pobieranie w tle działa w ten sposób:
- Informujesz przeglądarkę, aby wykonała grupę pobrań w tle.
- Przeglądarka pobiera te elementy i wyświetla użytkownikowi postęp.
- Gdy pobieranie się zakończy lub nie powiedzie, przeglądarka otworzy proces roboczy usługi i wyśle zdarzenie, aby poinformować Cię o tym, co się stało. W tym miejscu możesz zdecydować, co zrobić z odpowiedziami.
Jeśli po kroku 1 użytkownik zamknie strony Twojej witryny, nic się nie stanie – pobieranie będzie kontynuowane. Ponieważ pobieranie jest dobrze widoczne i można je łatwo przerwać, nie ma obaw o prywatność związanych ze zbyt długim zadaniem synchronizacji w tle. Ponieważ service worker nie działa nieustannie, nie ma obawy, że może nadużywać systemu, np. wydobywać bitcoiny w tle.
Na niektórych platformach (np. Androidzie) przeglądarka może się zamknąć po kroku 1, ponieważ może przekazać pobieranie danych systemowi operacyjnemu.
Jeśli użytkownik rozpocznie pobieranie w trybie offline lub przejdzie w tryb offline w trakcie pobierania, pobieranie w tle zostanie wstrzymane i wznowione później.
Interfejs API
Wykrywanie funkcji
Jak w przypadku każdej nowej funkcji, musisz sprawdzić, czy przeglądarka ją obsługuje. W przypadku pobierania w tle wystarczy:
if ('BackgroundFetchManager' in self) {
// This browser supports Background Fetch!
}
Rozpoczynanie pobierania w tle
Główny interfejs API jest powiązany z rejestracją skryptu service worker, więc najpierw zarejestruj skrypt service worker. Następnie:
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,
});
});
Funkcja backgroundFetch.fetch
przyjmuje 3 argumenty:
Parametry | |
---|---|
id |
string jednoznacznie identyfikuje to pobieranie w tle.
|
requests |
Array<Request|string>
Elementy do pobrania. Ciągi znaków będą traktowane jako adresy URL i przekształcane w Request za pomocą new Request(theString) .
Możesz pobierać dane z innych punktów początkowych, o ile zasoby na to zezwalają za pomocą CORS. Uwaga: Chrome nie obsługuje obecnie żądań, które wymagają wstępnego sprawdzenia CORS. |
options |
Obiekt, który może zawierać te elementy: |
options.title |
string Tytuł, który przeglądarka ma wyświetlać wraz z postępem. |
options.icons |
Array<IconDefinition> Tablica obiektów z polami „src”, „size” i „type”. |
options.downloadTotal |
number Łączny rozmiar treści odpowiedzi (po rozpakowaniu). Jest to opcjonalne, ale zdecydowanie zalecamy podanie tej informacji. Służy do informowania użytkownika o rozmiarze pobieranego pliku i postępach pobierania. Jeśli tego nie zrobisz, przeglądarka poinformuje użytkownika, że rozmiar jest nieznany, co może spowodować, że użytkownik zrezygnuje z pobierania. Jeśli liczba pobrań w tle przekroczy podaną tutaj wartość, pobieranie zostanie przerwane. Jeśli pobieranie zajmuje mniej miejsca niż |
backgroundFetch.fetch
zwraca obietnicę, która jest realizowana za pomocą obiektu BackgroundFetchRegistration
. Szczegóły omówię później. Obietnica jest odrzucana, jeśli użytkownik zrezygnował z pobierania lub jeden z podanych parametrów jest nieprawidłowy.
Wysyłanie wielu żądań dotyczących jednego pobierania w tle umożliwia łączenie elementów, które logicznie stanowią dla użytkownika jedną całość. Na przykład film może być podzielony na tysiące zasobów (co jest typowe w przypadku MPEG-DASH) i zawierać dodatkowe zasoby, takie jak obrazy. Poziom gry może być rozłożony na wiele zasobów JavaScript, obrazów i dźwięków. Dla użytkownika to po prostu „film” lub „poziom”.
Pobieranie istniejącego pobrania w tle
Istniejące pobieranie w tle możesz uzyskać w ten sposób:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});
…przekazując identyfikator żądanego pobierania w tle. get
zwraca undefined
, jeśli nie ma aktywnego pobierania w tle o tym identyfikatorze.
Pobieranie w tle jest uznawane za „aktywne” od momentu zarejestrowania do momentu, gdy zakończy się powodzeniem, niepowodzeniem lub zostanie przerwane.
Listę wszystkich aktywnych pobrań w tle możesz uzyskać za pomocą tego polecenia: getIds
navigator.serviceWorker.ready.then(async (swReg) => {
const ids = await swReg.backgroundFetch.getIds();
});
Rejestracje pobierania w tle
BackgroundFetchRegistration
(bgFetch
w przykładach powyżej) ma te elementy:
Właściwości | |
---|---|
id |
string Identyfikator pobierania w tle. |
uploadTotal |
number Liczba bajtów do wysłania na serwer. |
uploaded |
number Liczba bajtów, które zostały wysłane. |
downloadTotal |
number Wartość podana podczas rejestracji pobierania w tle lub zero. |
downloaded |
number Liczba bajtów, które zostały odebrane. Ta wartość może się zmniejszyć. Na przykład jeśli połączenie zostanie przerwane i pobieranie nie będzie mogło zostać wznowione, przeglądarka ponownie rozpocznie pobieranie tego zasobu od początku. |
result |
Jedna z tych wartości:
|
failureReason |
Jedna z tych wartości:
|
recordsAvailable |
boolean Czy można uzyskać dostęp do podstawowych żądań i odpowiedzi? Gdy ta wartość jest fałszywa, nie można używać |
Metody | |
abort() |
Zwraca Promise<boolean> Przerwij pobieranie w tle. Zwrócony obiekt Promise zostanie rozwiązany z wartością „true”, jeśli pobieranie zostało pomyślnie przerwane. |
matchAll(request, opts) |
Zwraca Promise<Array<BackgroundFetchRecord>> Pobieranie żądań i odpowiedzi. Argumenty są takie same jak w przypadku interfejsu API pamięci podręcznej. Wywołanie bez argumentów zwraca obietnicę wszystkich rekordów. Więcej informacji znajdziesz poniżej. |
match(request, opts) |
Zwraca Promise<BackgroundFetchRecord> jak wyżej, ale zwraca pierwsze dopasowanie. |
Wydarzenia | |
progress |
Wywoływane, gdy zmieni się dowolna z wartości uploaded , downloaded , result lub failureReason . |
Śledzenie postępów
Możesz to zrobić za pomocą zdarzenia progress
. Pamiętaj, że downloadTotal
to podana przez Ciebie wartość lub 0
, jeśli nie podasz żadnej wartości.
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}%`);
});
Otrzymywanie żądań i odpowiedzi
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
to BackgroundFetchRecord
, który wygląda tak:
Właściwości | |
---|---|
request |
Request Przesłana prośba. |
responseReady |
Promise<Response> Pobrana odpowiedź. Odpowiedź jest w stanie oczekiwania, ponieważ mogła jeszcze nie zostać odebrana. Obietnica zostanie odrzucona, jeśli pobieranie się nie powiedzie. |
Zdarzenia skryptu service worker
Wydarzenia | |
---|---|
backgroundfetchsuccess |
Wszystkie dane zostały pobrane. |
backgroundfetchfailure |
Co najmniej jedno pobranie nie powiodło się. |
backgroundfetchabort |
Co najmniej jedno pobieranie nie powiodło się.
Jest to przydatne tylko wtedy, gdy chcesz wyczyścić powiązane dane. |
backgroundfetchclick |
Użytkownik kliknął interfejs postępu pobierania. |
Obiekty zdarzeń mają te elementy:
Właściwości | |
---|---|
registration |
BackgroundFetchRegistration |
Metody | |
updateUI({ title, icons }) |
Umożliwia zmianę tytułu lub ikon, które zostały ustawione na początku. Jest to opcjonalne, ale w razie potrzeby możesz podać więcej informacji. Możesz to zrobić *tylko raz* podczas wydarzeń backgroundfetchsuccess i backgroundfetchfailure . |
Reagowanie na powodzenie lub niepowodzenie
Widzieliśmy już zdarzenie progress
, ale jest ono przydatne tylko wtedy, gdy użytkownik ma otwartą stronę Twojej witryny. Główną zaletą pobierania w tle jest to, że wszystko działa nadal po opuszczeniu strony przez użytkownika lub nawet po zamknięciu przeglądarki.
Jeśli pobieranie w tle zakończy się pomyślnie, Twój service worker otrzyma zdarzenie backgroundfetchsuccess
, a event.registration
będzie rejestracją pobierania w tle.
Po tym zdarzeniu pobrane żądania i odpowiedzi nie będą już dostępne, więc jeśli chcesz je zachować, przenieś je np. do interfejsu Cache API.
Podobnie jak w przypadku większości zdarzeń service workerów, użyj event.waitUntil
, aby service worker wiedział, kiedy zdarzenie się zakończy.
Na przykład w usłudze 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!' });
}());
});
Przyczyną niepowodzenia może być pojedynczy błąd 404, który nie był dla Ciebie ważny, więc nadal warto skopiować niektóre odpowiedzi do pamięci podręcznej, jak opisano powyżej.
Reagowanie na kliknięcie
Interfejs wyświetlający postęp i wynik pobierania jest klikalny. Zdarzenie backgroundfetchclick
w usłudze Service Worker umożliwia reagowanie na to zdarzenie. Jak wyżej, event.registration
będzie rejestracją pobierania w tle.
Najczęstszym działaniem związanym z tym zdarzeniem jest otwarcie okna:
addEventListener('backgroundfetchclick', (event) => {
const bgFetch = event.registration;
if (bgFetch.result === 'success') {
clients.openWindow('/latest-podcasts');
} else {
clients.openWindow('/download-progress');
}
});
Dodatkowe materiały
Korekta: w poprzedniej wersji tego artykułu funkcja pobierania w tle została błędnie określona jako „standard internetowy”. Interfejs API nie jest obecnie zgodny ze standardami. Specyfikację można znaleźć w WICG jako projekt raportu grupy społeczności.