Gdy wysyłasz dane na serwer WWW, czasami nie można zrealizować żądania. Przyczyną może być utrata połączenia przez użytkownika lub wyłączenie serwera. W każdym z tych przypadków możesz próbować ponownie wysłać żądania później.
Nowy interfejs BackgroundSync API stanowi idealne rozwiązanie tego problemu. Gdy skrypt service worker wykryje, że żądanie sieciowe nie zostało zrealizowane, może zarejestrować się w celu otrzymania zdarzenia sync
, które jest wysyłane, gdy przeglądarka uzna, że połączenie zostało przywrócone.
Pamiętaj, że zdarzenie synchronizacji może zostać dostarczone, nawet jeśli użytkownik opuści aplikację, dzięki czemu jest to znacznie skuteczniejsze niż tradycyjna metoda ponawiania nieudanych żądań.
Funkcja synchronizacji w tle ułatwia korzystanie z interfejsu BackgroundSync API oraz integrowanie jego wykorzystania z innymi modułami Workbox. Wdraża również strategię zastępczą dla przeglądarek, które nie korzystają jeszcze z funkcji BackgroundSync.
Przeglądarki, które obsługują interfejs BackgroundSync API, będą automatycznie odtwarzać w Twoim imieniu nieudane żądania w interwałie zarządzanym przez przeglądarkę, prawdopodobnie korzystając z wykładniczego ponowienia między kolejnymi próbami. W przeglądarkach, które natywnie nie obsługują interfejsu BackgroundSync API, synchronizacja w tle przez Workbox będzie automatycznie próbować ponownie odtworzyć po każdym uruchomieniu skryptu service worker.
Podstawowe użycie
Najprostszym sposobem korzystania z synchronizacji w tle jest użycie interfejsu Plugin
, który automatycznie dodaje nieudane żądania do kolejki i ponawia je po uruchomieniu przyszłych zdarzeń sync
.
import {BackgroundSyncPlugin} from 'workbox-background-sync';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';
const bgSyncPlugin = new BackgroundSyncPlugin('myQueueName', {
maxRetentionTime: 24 * 60, // Retry for max of 24 Hours (specified in minutes)
});
registerRoute(
/\/api\/.*\/*.json/,
new NetworkOnly({
plugins: [bgSyncPlugin],
}),
'POST'
);
BackgroundSyncPlugin
łączy się z wywołaniem zwrotnym wtyczki fetchDidFail
, a interfejs fetchDidFail
jest wywoływany tylko w przypadku zgłoszenia wyjątku, najprawdopodobniej w wyniku awarii sieci. Oznacza to, że żądania nie będą ponawiane, jeśli otrzymana odpowiedź ma stan błędu 4xx
lub 5xx
.
Jeśli chcesz ponawiać wszystkie żądania, które skutkują np. stanem 5xx
, możesz dodać do strategii wtyczkę fetchDidSucceed
:
const statusPlugin = {
fetchDidSucceed: ({response}) => {
if (response.status >= 500) {
// Throwing anything here will trigger fetchDidFail.
throw new Error('Server error.');
}
// If it's not 5xx, use the response as-is.
return response;
},
};
// Add statusPlugin to the plugins array in your strategy.
Zaawansowane użycie
Synchronizacja w tle Workbox udostępnia również klasę Queue
, do której możesz uruchamiać i dodawać nieudane żądania. Żądania zakończone niepowodzeniem są przechowywane w IndexedDB i ponawiane, gdy przeglądarka uzna, że łączność została przywrócona (czyli otrzyma zdarzenie synchronizacji).
Tworzenie kolejki
Aby utworzyć kolejkę synchronizacji w tle w Workbox, musisz ją utworzyć z nazwą kolejki (musi być unikalna dla Twojej źródła):
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
Nazwa kolejki jest częścią nazwy tagu, którą tag register()
jest szyfrowany przez globalny SyncManager
. Jest też używana jako nazwa magazynu obiektów bazy danych IndexedDB.
Dodawanie żądania do kolejki
Po utworzeniu instancji kolejki możesz dodawać do niej nieudane żądania.
Nieudane żądanie dodajesz przez wywołanie metody .pushRequest()
. Na przykład ten kod wykrywa wszystkie żądania, które się nie powiodły, i dodaje je do kolejki:
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
self.addEventListener('fetch', event => {
// Add in your own criteria here to return early if this
// isn't a request that should use background sync.
if (event.request.method !== 'POST') {
return;
}
const bgSyncLogic = async () => {
try {
const response = await fetch(event.request.clone());
return response;
} catch (error) {
await queue.pushRequest({request: event.request});
return error;
}
};
event.respondWith(bgSyncLogic());
});
Po dodaniu do kolejki żądanie jest automatycznie ponawiane, gdy skrypt service worker otrzyma zdarzenie sync
(co ma miejsce, gdy przeglądarka uzna, że łączność została przywrócona). Przeglądarki, które nie obsługują interfejsu BackgroundSync API, będą ponawiać próbę uruchomienia kolejki za każdym razem, gdy mechanizm Service Worker zostanie uruchomiony. Wymaga to uruchomienia strony sterującej skryptem service worker, więc nie będzie ono tak skuteczne.
Testowanie synchronizacji w tle
Niestety testowanie BackgroundSync jest w pewnym stopniu nieintuicyjne i trudne z wielu powodów.
Aby przetestować implementację, najlepiej wykonaj te czynności:
- Wczytaj stronę i zarejestruj skrypt service worker.
- Wyłącz sieć na komputerze lub wyłącz serwer WWW.
- NIE UŻYWAJ DEVTOOLÓW Chrome OFFLINE. Pole wyboru offline w Narzędziach deweloperskich ma wpływ tylko na żądania ze strony. Żądania skryptu Service Worker będą nadal realizowane.
- Twórz żądania sieciowe, które powinny zostać umieszczone w kolejce w ramach synchronizacji w tle z Workbox.
- Aby sprawdzić, czy żądania zostały dodane do kolejki, zajrzyj do narzędzia
Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
.
- Aby sprawdzić, czy żądania zostały dodane do kolejki, zajrzyj do narzędzia
- Teraz włącz sieć lub serwer WWW.
Wymuś wcześniejsze zdarzenie
sync
. Aby to zrobić, wejdź naChrome DevTools > Application > Service Workers
, wpisz nazwę taguworkbox-background-sync:<your queue name>
, gdzie<your queue name>
powinien być nazwą ustawionej kolejki, a następnie kliknij przycisk „Synchronizuj”.Żądania sieciowe powinny być realizowane w przypadku nieudanych żądań, a dane IndexedDB powinny być teraz puste, ponieważ żądania zostały ponownie odtworzone.
Typy
BackgroundSyncPlugin
Klasa implementująca wywołanie zwrotne cyklu życia fetchDidFail
. Ułatwia to dodawanie nieudanych żądań do kolejki synchronizacji w tle.
Właściwości
-
konstruktor
void
Funkcja
constructor
wygląda tak:(name: string, options?: QueueOptions) => {...}
-
nazwa
string,
Więcej informacji o parametrach znajdziesz w dokumentacji
workbox-background-sync.Queue
. -
Opcje
Opcjonalne QueueOptions
-
returns
-
Queue
Klasa do zarządzania przechowywaniem nieudanych żądań w IndexedDB i ponawianiu ich później. Wywołania zwrotne pozwalają obserwować wszystkie etapy procesu przechowywania i odtwarzania.
Właściwości
-
konstruktor
void
Tworzy instancję kolejki z podanymi opcjami
Funkcja
constructor
wygląda tak:(name: string, options?: QueueOptions) => {...}
-
nazwa
string,
Unikalna nazwa tej kolejki. Ta nazwa musi być unikalna, ponieważ jest używana do rejestrowania zdarzeń synchronizacji i przechowywania żądań w IndexedDB specyficznych dla tej instancji. W przypadku wykrycia zduplikowanej nazwy wyświetli się błąd.
-
Opcje
Opcjonalne QueueOptions
-
returns
-
-
nazwa
string,
-
getAll
void
Zwraca wszystkie wpisy, które nie wygasły (na
maxRetentionTime
). Wszystkie nieaktualne wpisy są usuwane z kolejki.Funkcja
getAll
wygląda tak:() => {...}
-
returns
Promise<QueueEntry[]>
-
-
popRequest
void
Usuwa i zwraca ostatnie żądanie w kolejce (wraz z jego sygnaturą czasową i metadanymi). Zwrócony obiekt ma postać:
{request, timestamp, metadata}
.Funkcja
popRequest
wygląda tak:() => {...}
-
returns
Promise<QueueEntry>
-
-
pushRequest
void
Zapisuje przekazane żądanie w IndexedDB (z jego sygnaturą czasową i metadanymi) na końcu kolejki.
Funkcja
pushRequest
wygląda tak:(entry: QueueEntry) => {...}
-
wpis
QueueEntry
-
returns
Promise<void>
-
-
registerSync
void
Rejestruje zdarzenie synchronizacji z tagiem unikalnym dla tej instancji.
Funkcja
registerSync
wygląda tak:() => {...}
-
returns
Promise<void>
-
-
replayRequests
void
Przewija każde żądanie w kolejce i próbuje je ponownie pobrać. Jeśli jakiekolwiek żądanie nie zostanie pobrane ponownie, zostanie umieszczone na tym samym miejscu w kolejce (co spowoduje zarejestrowanie ponownej próby dla następnego zdarzenia synchronizacji).
Funkcja
replayRequests
wygląda tak:() => {...}
-
returns
Promise<void>
-
-
shiftRequest
void
Usuwa i zwraca pierwsze żądanie w kolejce (wraz z jego sygnaturą czasową i metadanymi). Zwrócony obiekt ma postać:
{request, timestamp, metadata}
.Funkcja
shiftRequest
wygląda tak:() => {...}
-
returns
Promise<QueueEntry>
-
-
rozmiar
void
Zwraca liczbę pozycji w kolejce. Pamiętaj, że ta liczba uwzględnia też nieaktualne wpisy (na
maxRetentionTime
).Funkcja
size
wygląda tak:() => {...}
-
returns
Obietnica<number>
-
-
unshiftRequest
void
Zapisuje przekazane żądanie w IndexedDB (z jego sygnaturą czasową i metadanymi) na początku kolejki.
Funkcja
unshiftRequest
wygląda tak:(entry: QueueEntry) => {...}
-
wpis
QueueEntry
-
returns
Promise<void>
-
QueueOptions
Właściwości
-
forceSyncFallback
wartość logiczna opcjonalna
-
maxRetentionTime
Liczba opcjonalnie
-
onSync
OnSyncCallback opcjonalnie
QueueStore
Klasa do zarządzania przechowywaniem żądań z kolejki w IndexedDB, indeksowana według nazwy kolejki w celu ułatwienia dostępu.
Większość programistów nie musi mieć bezpośredniego dostępu do tych zajęć. Są one dostępne w zaawansowanych przypadkach użycia.
Właściwości
-
konstruktor
void
Wiąże tę instancję z instancją kolejki, dzięki czemu dodane wpisy można zidentyfikować na podstawie nazwy kolejki.
Funkcja
constructor
wygląda tak:(queueName: string) => {...}
-
queueName
string,
-
returns
-
-
deleteEntry
void
Usuwa wpis z podanym identyfikatorem.
OSTRZEŻENIE: ta metoda nie gwarantuje, że usunięty wpis będzie należeć do tej kolejki (tzn. będzie pasować do
queueName
). To ograniczenie jest jednak akceptowalne, ponieważ ta klasa nie jest dostępna publicznie. Dodatkowa weryfikacja spowolniłaby działanie tej metody.Funkcja
deleteEntry
wygląda tak:(id: number) => {...}
-
id
Liczba
-
returns
Promise<void>
-
-
getAll
void
Zwraca wszystkie wpisy w sklepie pasujące do wartości
queueName
.Funkcja
getAll
wygląda tak:() => {...}
-
returns
Promise<QueueStoreEntry[]>
-
-
popEntry
void
Usuwa i zwraca ostatni wpis w kolejce zgodny z
queueName
.Funkcja
popEntry
wygląda tak:() => {...}
-
returns
Promise<QueueStoreEntry>
-
-
pushEntry
void
Dołącz wpis jako ostatni w kolejce.
Funkcja
pushEntry
wygląda tak:(entry: UnidentifiedQueueStoreEntry) => {...}
-
wpis
UnidentifiedQueueStoreEntry
-
returns
Promise<void>
-
-
shiftEntry
void
Usuwa i zwraca pierwszy wpis w kolejce zgodny z
queueName
.Funkcja
shiftEntry
wygląda tak:() => {...}
-
returns
Promise<QueueStoreEntry>
-
-
rozmiar
void
Zwraca liczbę wpisów w sklepie pasujących do
queueName
.Funkcja
size
wygląda tak:() => {...}
-
returns
Obietnica<number>
-
-
unshiftEntry
void
Dołącz wpis jako pierwszy na początku kolejki.
Funkcja
unshiftEntry
wygląda tak:(entry: UnidentifiedQueueStoreEntry) => {...}
-
wpis
UnidentifiedQueueStoreEntry
-
returns
Promise<void>
-
StorableRequest
Klasa ułatwiająca serializację i deserializację żądań, co umożliwia ich przechowywanie w IndexedDB.
Większość programistów nie musi mieć bezpośredniego dostępu do tych zajęć. Są one dostępne w zaawansowanych przypadkach użycia.
Właściwości
-
konstruktor
void
Akceptuje obiekt danych żądania, którego można użyć do utworzenia
Request
, ale można go też przechowywać w IndexedDB.Funkcja
constructor
wygląda tak:(requestData: RequestData) => {...}
-
requestData
RequestData
Obiekt danych żądania zawierający właściwość
url
oraz wszystkie istotne właściwości właściwości [requestInit]https://fetch.spec.whatwg.org/#requestinit
.
-
returns
-
-
klon,
void
Tworzy i zwraca głęboką kopię instancji.
Funkcja
clone
wygląda tak:() => {...}
-
returns
-
-
toObject
void
Zwraca głęboką kopię obiektu instancji
_requestData
.Funkcja
toObject
wygląda tak:() => {...}
-
returns
RequestData
-
-
toRequest
void
Konwertuje tę instancję na żądanie.
Funkcja
toRequest
wygląda tak:() => {...}
-
returns
Prośba
-
-
fromRequest
void
Konwertuje obiekt Request na zwykły obiekt, który można sklonować lub zakodować w postaci ciągu znaków w formacie JSON.
Funkcja
fromRequest
wygląda tak:(request: Request) => {...}
-
Poproś
Prośba
-
returns
Promise<StorableRequest>
-