W 2015 roku wprowadziliśmy synchronizację w tle, która umożliwia skryptowi service worker odłożenie zadania do momentu uzyskania połączenia przez użytkownika. Oznacza to, że użytkownik może wpisać wiadomość, kliknąć Wyślij i opuścić stronę, wiedząc, że wiadomość zostanie wysłana teraz lub po nawiązaniu połączenia.
Jest to przydatna funkcja, ale wymaga, aby skrypt service worker był aktywny przez cały czas pobierania danych. Nie stanowi to problemu w przypadku krótkich zadań, takich jak wysłanie wiadomości, ale jeśli zadanie trwa zbyt długo, przeglądarka wyłącza mechanizm Service Worker, ponieważ w przeciwnym razie istnieje ryzyko dla prywatności i baterii użytkownika.
A co w sytuacji, gdy chcesz pobrać coś, co może zająć dużo czasu, np. film, podcasty czy poziomy gry? Właśnie do tego służy funkcja pobierania w tle.
Pobieranie w tle jest dostępne domyślnie od Chrome 74.
Oto krótka dwuminutowa prezentacja przedstawiająca tradycyjny stan rzeczy w porównaniu z korzystaniem z pobierania w tle:
Wypróbuj wersję demonstracyjną i przejrzyj kod.
Jak to działa
Pobieranie w tle działa w ten sposób:
- Kazasz przeglądarce wykonać grupę pobrań w tle.
- Przeglądarka pobiera te dane i wyświetla je użytkownikowi.
- Gdy pobieranie się zakończy lub nie uda się go pobrać, przeglądarka otworzy skrypt service worker i uruchomi zdarzenie, aby poinformować Cię, co się stało. Na tym etapie decydujesz, co zrobić z odpowiedziami (jeśli tak jest).
Jeśli po wykonaniu kroku 1 użytkownik zamknie strony witryny, pobieranie będzie kontynuowane. Ponieważ pobieranie jest bardzo widoczne i łatwe do przerwania, nie ma obaw o ochronę prywatności w związku ze zbyt długim zadaniem synchronizacji w tle. Skrypt service worker nie działa stale, dlatego nie ma obaw, że może nadużywać systemu, np. wydobywać bitcoiny w tle.
Na niektórych platformach (np. w Androidzie) możliwe jest zamknięcie przeglądarki po wykonaniu kroku 1, ponieważ przeglądarka może przekazać pobieranie do systemu operacyjnego.
Jeśli użytkownik rozpocznie pobieranie w trybie offline lub przejdzie w tryb offline, pobieranie w tle zostanie wstrzymane i wznowione później.
Interfejs API
Wykrywanie cech
Tak jak w przypadku każdej nowej funkcji, warto sprawdzić, czy przeglądarka ją obsługuje. Aby pobrać w tle, wystarczy:
if ('BackgroundFetchManager' in self) {
// This browser supports Background Fetch!
}
Rozpoczynam pobieranie w tle
Główny interfejs API jest zawieszony przy rejestracji skryptu service worker, dlatego najpierw zarejestruj taki skrypt. 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 pobieranie w tle.
|
requests |
Array<Request|string>
Elementy do pobrania. Ciągi tekstowe będą traktowane jako adresy URL i zamieniane w elementy typu Request za pomocą new Request(theString) .
Możesz pobierać elementy z innych źródeł, o ile pozwalają na to zasoby przez CORS. Uwaga: Chrome obecnie nie obsługuje żądań, które wymagałyby procesu wstępnego CORS. |
options |
Obiekt, który może obejmować: |
options.title |
string Tytuł przeglądarki, który wyświetla się wraz z postępem. |
options.icons |
Array<IconDefinition> Tablica obiektów o wartościach „src”, „size” i „type”. |
options.downloadTotal |
number Łączny rozmiar treści odpowiedzi (po wyjęciu z pliku gzip). Chociaż jest to opcjonalne, zdecydowanie zalecamy jego podanie. Informuje on użytkownika o rozmiarze pobieranego pliku i informuje o postępach. Jeśli tego nie zrobisz, przeglądarka poinformuje użytkownika, że rozmiar jest nieznany, co może spowodować przerwanie pobierania. Jeśli pobieranie w tle przekroczy liczbę podaną w tym miejscu, zostanie przerwane. Nie ma problemu, jeśli pobierany plik jest mniejszy niż |
backgroundFetch.fetch
zwraca obietnicę, która kończy się wartością BackgroundFetchRegistration
. Później podam szczegóły. Obietnica zostanie odrzucona, jeśli użytkownik zrezygnował z pobierania lub jeden z podanych parametrów jest nieprawidłowy.
Udostępnienie wielu żądań w ramach jednego pobierania w tle umożliwia łączenie w sobie różnych elementów, które logicznie są traktowane jako jedna rzecz dla użytkownika. Na przykład film można podzielić na tysiące zasobów (typowych w przypadku MPEG-DASH) i udostępnić im dodatkowe zasoby, takie jak obrazy. Poziom gry może obejmować wiele zasobów JavaScript, graficznych i audio. Dla użytkownika jest to jednak po prostu „film” albo „poziom”.
Pobieram dotychczasowe pobieranie w tle
Pobieranie w tle może wyglądać tak:
navigator.serviceWorker.ready.then(async (swReg) => {
const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});
...przesyłając parametr id żądanego pobierania tła. get
zwraca wartość undefined
, jeśli nie ma aktywnego pobierania w tle o tym identyfikatorze.
Pobieranie w tle jest uznawane za „aktywne” od momentu zarejestrowania, aż do momentu powodzenia, niepowodzenia lub przerwania.
Listę wszystkich aktywnych pobrań w tle możesz wyświetlić, korzystając z getIds
:
navigator.serviceWorker.ready.then(async (swReg) => {
const ids = await swReg.backgroundFetch.getIds();
});
Rejestracje pobierania w tle
Element BackgroundFetchRegistration
(bgFetch
w powyższych przykładach) zawiera:
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 wysłanych. |
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 przerwane i nie można wznowić pobierania, w takim przypadku przeglądarka ponownie uruchomi pobieranie tego zasobu od zera. |
result |
Jedna z tych wersji:
|
failureReason |
Jedna z tych wersji:
|
recordsAvailable |
boolean Czy można uzyskać dostęp do powiązanych z nimi żądań i odpowiedzi? Jeśli ma wartość fałsz, nie można używać |
Metody | |
abort() |
Zwraca Promise<boolean> Przerwij pobieranie w tle. Zwrócona obietnica znika z wartością true, jeśli pobieranie zostało przerwane. |
matchAll(request, opts) |
Zwraca Promise<Array<BackgroundFetchRecord>> Otrzymuj żądania i odpowiedzi. Argumenty są takie same jak w przypadku interfejsu 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> Tak jak powyżej, ale rozstrzyga się w przypadku pierwszego dopasowania. |
Wydarzenia | |
progress |
Uruchamiane, gdy zmieni się dowolna z tych wartości: uploaded , downloaded , result lub failureReason . |
Śledzenie postępów
Możesz to zrobić za pomocą zdarzenia progress
. Pamiętaj, że downloadTotal
to dowolna wartość, którą podasz, lub 0
, jeśli jej nie podasz.
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}%`);
});
Uzyskiwanie żą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
i wygląda tak:
Właściwości | |
---|---|
request |
Request Przesłane żądanie. |
responseReady |
Promise<Response> Pobrana odpowiedź. Odpowiedź jest przygotowana z obietnicą, ponieważ być może jeszcze do Ciebie nie dotarła. Obietnica zostanie odrzucona, jeśli pobieranie się nie powiedzie. |
Zdarzenia skryptu service worker
Wydarzenia | |
---|---|
backgroundfetchsuccess |
Wszystko zostało pobrane. |
backgroundfetchfailure |
Co najmniej 1 pobieranie zakończyło się niepowodzeniem. |
backgroundfetchabort |
Nie udało się pobrać co najmniej 1 pobrania.
Jest to naprawdę przydatne tylko wtedy, gdy chcesz wyczyścić powiązane dane. |
backgroundfetchclick |
Użytkownik kliknął interfejs postępu pobierania. |
Obiekty zdarzeń mają te atrybuty:
Właściwości | |
---|---|
registration |
BackgroundFetchRegistration |
Metody | |
updateUI({ title, icons }) |
Umożliwia zmianę początkowo ustawionego tytułu/ikony. Jest to opcjonalne, ale w razie potrzeby pozwala podać więcej kontekstu. Możesz to zrobić tylko raz podczas wydarzeń backgroundfetchsuccess i backgroundfetchfailure . |
Reagowanie na sukces/porażki
Widzieliśmy już zdarzenie progress
, ale jest ono przydatne tylko wtedy, gdy użytkownik ma otwartą stronę z Twoją witryną. 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 się zakończy, skrypt 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. Jeśli chcesz je zachować, przenieś je gdzieś w stylu cache API.
Tak jak w przypadku większości zdarzeń skryptu service worker, użyj event.waitUntil
, aby mechanizm Service Worker wiedział o jego zakończeniu.
Na przykład w skryptu 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!' });
}());
});
Niepowodzenie może sprowadzać się do pojedynczego błędu 404, który być może nie był dla Ciebie ważny, dlatego nadal warto skopiować niektóre odpowiedzi do pamięci podręcznej w sposób opisany powyżej.
Reakcja na kliknięcie
Interfejs, w którym widać postęp pobierania i wynik, można kliknąć. Zdarzenie backgroundfetchclick
w skrypcie service worker pozwala na to zareagować. Tak jak powyżej, event.registration
będzie rejestrować pobieranie w tle.
Typowe czynności związane z tym zdarzeniem to otwarcie okna:
addEventListener('backgroundfetchclick', (event) => {
const bgFetch = event.registration;
if (bgFetch.result === 'success') {
clients.openWindow('/latest-podcasts');
} else {
clients.openWindow('/download-progress');
}
});
Dodatkowe zasoby
Poprawka: poprzednia wersja tego artykułu błędnie określała pobieranie w tle jako „standardu internetowego”. Interfejs API nie jest obecnie zgodny z standardami. Specyfikację można znaleźć w WICG w formie roboczej wersji raportu dotyczącego grupy społeczności.