W 2015 r. wprowadziliśmy synchronizację w tle, która umożliwia opóźnianie pracy przez service 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 Chrome 74.
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 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, nie ma problemu, pobieranie będzie kontynuowane. Pobieranie jest dobrze widoczne i łatwo je przerwać, więc 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 tutaj limit, zostaną 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ą. 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. Jeden poziom gry może być rozłożony na wiele zasobów JavaScript, obrazów i dźwięku. Ale dla użytkownika jest to po prostu „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 zero. |
downloaded | number Liczba bajtów odebranych pomyślnie. Ta wartość może się zmniejszyć. Jeśli na przykład połączenie zostanie utracone i nie można wznowić pobierania, 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 się 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 na podanie dodatkowych informacji. 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ę Twojej witryny. 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ć, przenieś je 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, więc 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ł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, a specyfikację można znaleźć w WICG jako raport Draft Community Group.