W 2015 r. wprowadziliśmy synchronizację w tle, która umożliwia opóźnianie pracy przez usługę workera do momentu, gdy użytkownik uzyska połączenie z internetem. Oznacza to, że użytkownik może wpisać wiadomość, kliknąć „Wyślij” i opuścić stronę, wiedząc, że wiadomość zostanie wysłana albo teraz, albo gdy będzie miał połączenie z internetem.
Jest to przydatna funkcja, ale wymaga, aby usługa była aktywna przez cały czas 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 zabije service workera. W przeciwnym razie może to stanowić zagrożenie dla prywatności i baterii użytkownika.
Co zrobić, jeśli chcesz pobrać coś, co może zająć dużo czasu, np. film, podcasty lub poziomy w grze? Do tego służy pobieranie w tle.
Pobieranie w tle jest dostępne domyślnie od wersji 74 przeglądarki Chrome.
Oto 2-minutowy film demonstrujący tradycyjny stan rzeczy w porównaniu z wykorzystaniem funkcji pobierania w tle:
Wypróbuj wersję demonstracyjną i przejrzyj kod.
Jak to działa
Pobranie w tle działa w ten sposób:
- Informujesz przeglądarkę, aby wykonała grupę pobierania w tle.
- Przeglądarka pobiera te elementy, wyświetlając użytkownikowi postęp.
- Gdy pobieranie się zakończy (lub zakończy się niepowodzeniem), przeglądarka otwiera Twoje narzędzie związane z usługami i wywołuje zdarzenie, aby poinformować Cię o wyniku. Tutaj decydujesz, co zrobić z otrzymanymi odpowiedziami.
Jeśli użytkownik zamknie strony Twojej witryny po kroku 1, nic się nie stanie – pobieranie będzie kontynuowane. Ponieważ pobieranie jest dobrze widoczne i łatwo je przerwać, nie ma obaw o prywatność w przypadku zbyt długiego zadania synchronizacji w tle. Ponieważ usługa w tle nie działa stale, nie ma obaw, że będzie nadużywać systemu, np. wydobywając bitcoiny w tle.
Na niektórych platformach (np. Androidzie) przeglądarka może się zamknąć po kroku 1, ponieważ może przekazać pobieranie do systemu operacyjnego.
Jeśli użytkownik rozpocznie pobieranie w trybie offline lub utraci połączenie w trakcie pobierania, pobieranie w tle zostanie wstrzymane i wznowione później.
Interfejs API
Wykrywanie funkcji
Podobnie jak w przypadku każdej nowej funkcji, musisz sprawdzić, czy przeglądarka ją obsługuje. Pobranie w tle działa tak:
if ('BackgroundFetchManager' in self) {
// This browser supports Background Fetch!
}
Uruchamianie pobierania w tle
Główny interfejs API jest zależny od rejestracji skryptu service worker, więc upewnij się, że najpierw zarejestrowałeś 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 identyfikuje w wyjątkowy sposób 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ą funkcji new Request(theString) .
Możesz pobierać dane z innych źródeł, o ile pozwalają na to te zasoby za pomocą CORS. Uwaga: Chrome nie obsługuje obecnie żądań, które wymagają wstępnej weryfikacji CORS. |
options |
Obiekt, który może zawierać: |
options.title |
string Tytuł, który przeglądarka ma wyświetlać wraz z postępem. |
options.icons |
Array<IconDefinition> Tablica obiektów z atrybutami „src”, „size” i „type”. |
options.downloadTotal |
number Łączny rozmiar treści odpowiedzi (po rozpakowaniu). Chociaż jest to opcjonalne, zdecydowanie zalecamy podanie tej informacji. Jest ona używana do informowania użytkownika o rozmiarze pliku do pobrania i o postępie pobierania. Jeśli tego nie zrobisz, przeglądarka poinformuje użytkownika, że rozmiar jest nieznany, przez co może on szybciej przerwać pobieranie. Jeśli pobrania w tle przekroczą podany tu limit, zostaną przerwane. Nie ma znaczenia, czy pobieranie jest mniejsze niż |
backgroundFetch.fetch
zwraca obietnicę, która zwraca wartość BackgroundFetchRegistration
. Szczegóły tej funkcji omówię później. Obietnica jest odrzucana, jeśli użytkownik zrezygnował z pobierania lub jeden z podanych parametrów jest nieprawidłowy.
Przesyłanie wielu żądań w ramach pojedynczego pobierania w tle umożliwia łączenie elementów, które z logicznego punktu widzenia są dla użytkownika jedną rzeczą. Na przykład film może być podzielony na tysiące zasobów (co jest typowe dla MPEG-DASH) i zawierać dodatkowe zasoby, takie jak obrazy. Poszczególne poziomy gry mogą być rozmieszczone w wielu zasobach JavaScript, obrazów i dźwięku. Ale dla użytkownika to tylko „film” lub „poziom”.
Pobieranie istniejącego pliku w tle
Możesz uzyskać istniejące pobieranie w tle w ten sposób:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});
…przekazując identyfikator pobierania w tle, którego chcesz użyć. Funkcja get
zwraca undefined
, jeśli nie ma aktywnego pobierania w tle z tym identyfikatorem.
Pobieranie w tle jest uważane za „aktywne” od momentu zarejestrowania do momentu, gdy zakończy się powodzeniem, zakończy się niepowodzeniem lub zostanie przerwane.
Listę wszystkich aktywnych pobierania w tle możesz uzyskać za pomocą getIds
:
navigator.serviceWorker.ready.then(async (swReg) => {
const ids = await swReg.backgroundFetch.getIds();
});
Rejestracje pobierania w tle
Element BackgroundFetchRegistration
(bgFetch
w przypadkach powyżej) ma:
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 wysłanych pomyślnie. |
downloadTotal |
number Wartość podana podczas rejestrowania pobierania w tle lub 0. |
downloaded |
number Liczba bajtów, które zostały odebrane. Ta wartość może się zmniejszyć. Jeśli na przykład połączenie zostanie utracone i pobieranie nie może zostać wznowione, przeglądarka 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 żądań i odpowiedzi? Gdy to pole ma wartość Fałsz, nie można użyć wartości |
Metody | |
abort() |
Zwraca Promise<boolean> Anuluj pobieranie w tle. Zwrócona obietnica zwraca wartość true, jeśli pobranie zostało przerwane. |
matchAll(request, opts) |
Zwraca Promise<Array<BackgroundFetchRecord>> Get the requests and responses. Argumenty są takie same jak w interfejsie API pamięci podręcznej. Wywołanie bez argumentów zwraca obietnicę dla wszystkich rekordów. Więcej informacji znajdziesz poniżej. |
match(request, opts) |
Zwraca Promise<BackgroundFetchRecord> Jak wyżej, ale rozwiązuje z pierwszym dopasowaniem. |
Wydarzenia | |
progress |
Wywoływany, gdy zmieni się wartość właściwości uploaded , downloaded , result lub failureReason . |
Śledzenie postępów
Można to zrobić za pomocą zdarzenia progress
. Pamiętaj, że downloadTotal
to dowolna wartość, którą podano, lub 0
, jeśli nie podano 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}%`);
});
Pobieranie żą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 Prośba, która została przesłana. |
responseReady |
Promise<Response> Odebrana odpowiedź. Odpowiedź jest opóźniona, ponieważ może jeszcze nie zostać otrzymana. Jeśli pobranie się nie powiedzie, obietnica zostanie odrzucona. |
Zdarzenia skryptu service worker
Wydarzenia | |
---|---|
backgroundfetchsuccess |
Wszystkie dane zostały pobrane. |
backgroundfetchfailure |
Co najmniej jedno z pobierania zakończyło się niepowodzeniem. |
backgroundfetchabort |
Co najmniej 1 pobieranie zakończyło się niepowodzeniem.
Jest to przydatne tylko wtedy, gdy chcesz oczyścić powiązane dane. |
backgroundfetchclick |
Użytkownik kliknął interfejs użytkownika pokazujący postęp pobierania. |
Obiekty zdarzeń mają:
Właściwości | |
---|---|
registration |
BackgroundFetchRegistration |
Metody | |
updateUI({ title, icons }) |
Umożliwia zmianę początkowo ustawionego tytułu lub ikon. Jest to opcjonalne, ale w razie potrzeby pozwala dodać więcej kontekstu. Możesz to zrobić tylko *raz* podczas wydarzeń backgroundfetchsuccess i backgroundfetchfailure . |
Odpowiedź na powodzenie lub niepowodzenie
Zdarzenie progress
jest już znane, ale jest przydatne tylko wtedy, gdy użytkownik ma otwartą stronę w Twojej witrynie. Główną zaletą pobierania w tle jest to, że aplikacja działa nadal, gdy użytkownik opuszcza stronę lub zamyka przeglądarkę.
Jeśli pobieranie w tle zostanie ukończone, usługa robocza otrzyma zdarzenie backgroundfetchsuccess
, a event.registration
będzie rejestracją pobierania w tle.
Po tym zdarzeniu pobrane żądania i odpowiedzi nie są już dostępne, więc jeśli chcesz je zachować, przełóż je w inne miejsce, np. do interfejsu API pamięci podręcznej.
Podobnie jak w przypadku większości zdarzeń usługi, użyj funkcji event.waitUntil
, aby usługa wiedziała, kiedy zdarzenie się zakończyło.
Na przykład w usługach:
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!' });
}());
});
Niepowodzenie może być spowodowane pojedynczym błędem 404, który może nie być dla Ciebie ważny, dlatego warto skopiować niektóre odpowiedzi do pamięci podręcznej w sposób opisany powyżej.
Reakcja na kliknięcie
Interfejs wyświetlający postęp i wynik pobierania jest klikalny. Zdarzenie backgroundfetchclick
w usługach w tle pozwala na reakcję na to zdarzenie. Jak wspomniano powyżej, event.registration
będzie rejestracją pobierania w tle.
Zwykle w przypadku tego zdarzenia otwiera się okno:
addEventListener('backgroundfetchclick', (event) => {
const bgFetch = event.registration;
if (bgFetch.result === 'success') {
clients.openWindow('/latest-podcasts');
} else {
clients.openWindow('/download-progress');
}
});
Dodatkowe materiały
Poprawka: w poprzedniej wersji tego artykułu nieprawidłowo określono pobieranie w tle jako „standard sieci”. Interfejs API nie jest obecnie standardem, ale specyfikację można znaleźć w WICG jako raport Draft Community Group.