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 skrypt service worker był aktywny 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 więc możesz zrobić w sytuacji, gdy potrzebujesz pobrać coś, co zajmuje dużo czasu – np. filmu, podcastu lub poziomu gry. 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:
- Mówisz przeglądarce, aby wykonywała w tle grupę pobierania.
- Przeglądarka pobiera te dane, a następnie wyświetla użytkownikowi postęp.
- Gdy pobieranie się zakończy lub zakończy się niepowodzeniem, przeglądarka otworzy Twoje narzędzie związane z usługami i wygeneruje 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. Skrypt service worker nie jest stale uruchomiony, więc nie ma obaw, że może on 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 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 zawiesza rejestrację skryptu service worker, dlatego najpierw musisz go zarejestrować. 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 będą traktowane jako adresy URL i zapisywane jako 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 wyświetla się w przeglądarce 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 postępie pobierania. Jeśli go nie podasz, przeglądarka poinformuje użytkownika, że rozmiar jest nieznany, co może zwiększyć prawdopodobieństwo przerwania pobierania. Jeśli liczba pobrań w tle przekroczy podany tu limit, pobieranie zostanie przerwane. Nie ma znaczenia, czy pobieranie jest mniejsze niż |
backgroundFetch.fetch
zwraca obietnicę, która zwraca wartość BackgroundFetchRegistration
. Szczegóły tej kwestii 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 połączenie elementów, które z logicznego punktu widzenia są dla użytkownika jedną rzeczą. Film może na przykład składać się z tysiąca zasobów (co jest typowe dla MPEG-DASH) oraz 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 chodzi tylko o „film”, „poziom”.
Uzyskiwanie istniejącego pobierania 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 id pobierania w tle, które chcesz wykonać. 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, które mają zostać wysłane do serwera. |
uploaded |
number Liczba bajtów, które zostały wysłane. |
downloadTotal |
number Wartość podana podczas rejestrowania pobierania w tle lub zero. |
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 ma wartość Fałsz, nie można używać |
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 podana wartość lub 0
, jeśli wartość nie została podana.
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> Pobrana odpowiedź. Odpowiedź jest opóźniona, ponieważ może jeszcze nie zostać otrzymana. Jeśli pobranie się nie powiedzie, obietnica zostanie odrzucona. |
Zdarzenia Service Worker
Wydarzenia | |
---|---|
backgroundfetchsuccess |
Udało się pobrać wszystko. |
backgroundfetchfailure |
Nie udało się pobrać co najmniej jednego pliku. |
backgroundfetchabort |
Co najmniej 1 pobieranie zakończyło się niepowodzeniem.
Jest to przydatne tylko wtedy, gdy chcesz usunąć 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 ustawionych tytułów 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ż dostępne, ale jest przydatne tylko wtedy, gdy użytkownik ma otwartą stronę w Twojej witrynie. Główną zaletą pobierania w tle jest to, że wszystko działa, gdy użytkownik opuści stronę lub nawet zamknie 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ć, przenieś je do interfejsu API pamięci podręcznej.
Podobnie jak w przypadku większości zdarzeń skryptu service worker, należy użyć event.waitUntil
, aby taki skrypt znał powiadomienie o zakończeniu zdarzenia.
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, więc warto skopiować niektóre odpowiedzi do pamięci podręcznej, jak opisano powyżej.
Reakcja na kliknięcie
Interfejs wyświetlający postęp i wynik pobierania jest klikalny. Zdarzenie backgroundfetchclick
w usługowym workerze 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 grupy roboczej.