Quando invii dati a un server web, a volte le richieste non vanno a buon fine. Il motivo potrebbe essere che l'utente ha perso la connettività o che il server non è attivo; in entrambi i casi, potresti voler provare a inviare di nuovo le richieste in un secondo momento.
La nuova API BackgroundSync
rappresenta la soluzione ideale a questo problema. Quando un service worker rileva che una richiesta di rete non è andata a buon fine, può registrarsi per ricevere un evento sync
, che viene consegnato quando il browser ritiene che sia tornata la connettività.
Tieni presente che l'evento di sincronizzazione può essere pubblicato anche se l'utente ha abbandonato l'applicazione, il che significa che è molto più efficace rispetto al metodo tradizionale di ritentare le richieste non riuscite.
La sincronizzazione in background di Workbox è progettata per semplificare l'utilizzo dell'API BackgroundSync e integrarne l'utilizzo con altri moduli di Workbox. Implementa inoltre una strategia di riserva per i browser che non implementano ancora BackgroundSync.
I browser che supportano l'API BackgroundSync riprodurranno automaticamente le richieste non riuscite per tuo conto a un intervallo gestito dal browser, probabilmente utilizzando il backoff esponenziale tra i tentativi di riproduzione. Nei browser che non supportano in modo nativo l'API BackgroundSync, Workbox Background Sync proverà automaticamente a ripetere la riproduzione ogni volta che viene avviato il service worker.
Utilizzo di base
Il modo più semplice di utilizzare la sincronizzazione in background è utilizzare Plugin
, che accoda automaticamente le richieste non riuscite e le riprova quando vengono attivati futuri eventi 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
si aggancia al
callback del plug-in fetchDidFail
e
fetchDidFail
viene richiamato solo se viene generata un'eccezione, molto probabilmente
a causa di un errore di rete. Ciò significa che le richieste non verranno ritentate se viene ricevuta una risposta con uno stato di errore 4xx
o 5xx
.
Se vuoi riprovare tutte le richieste che risultano, ad esempio, uno stato 5xx
, puoi farlo aggiungendo un plug-in fetchDidSucceed
alla tua strategia:
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.
Utilizzo avanzato
La sincronizzazione in background della casella di lavoro fornisce anche un corso Queue
, che puoi
instaurare e aggiungere le richieste non riuscite. Le richieste non riuscite vengono archiviate in IndexedDB e vengono tentate di nuovo quando il browser ritiene che la connettività sia ripristinata, ovvero quando riceve l'evento di sincronizzazione.
Creazione di una coda
Per creare una coda di sincronizzazione in background della casella di lavoro, devi crearla con un nome coda (che deve essere univoco per la tua origine):
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
Il nome della coda viene utilizzato come parte del nome del tag che viene
register()
assegnato
dal
SyncManager
globale. Viene utilizzato anche come nome dell'archivio oggetti per il database IndexedDB.
Aggiunta di una richiesta alla coda
Dopo aver creato l'istanza Queue, puoi aggiungere richieste non riuscite.
Per aggiungere una richiesta non riuscita, richiama il metodo .pushRequest()
. Ad esempio, il seguente codice rileva tutte le richieste non riuscite e le aggiunge alla coda:
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());
});
Una volta aggiunta alla coda, la richiesta viene tentata automaticamente quando il service worker riceve l'evento sync
(cosa che si verifica quando il browser ritiene che la connettività sia ripristinata). I browser che non supportano l'API BackgroundSync ritenteranno la coda a ogni avvio del service worker. Ciò richiede l'esecuzione della pagina che controlla il service worker, quindi non sarà molto efficace.
Test della sincronizzazione in background della casella di lavoro
Sfortunatamente, testare BackgroundSync è un po' poco intuitivo e difficile per una serie di motivi.
L'approccio migliore per testare la tua implementazione è:
- Carica una pagina e registra il tuo service worker.
- Disattiva la rete del computer o il server web.
- NON UTILIZZARE CHROME DEVTOOLS OFFLINE. La casella di controllo offline in DevTools interessa solo le richieste dalla pagina. Le richieste dei service worker continuano ad andare a buon fine.
- Effettua le richieste di rete da mettere in coda con la sincronizzazione in background della casella di lavoro.
- Puoi verificare che le richieste siano state in coda cercando in
Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
- Puoi verificare che le richieste siano state in coda cercando in
- Ora attiva la rete o il server web.
Per forzare un evento
sync
in anteprima, vai aChrome DevTools > Application > Service Workers
, inserisci il nome tag diworkbox-background-sync:<your queue name>
, dove<your queue name>
dovrebbe essere il nome della coda impostata, quindi fai clic sul pulsante "Sincronizza".Dovresti vedere che le richieste di rete vengono completate per le richieste non riuscite. Ora i dati IndexedDB dovrebbero essere vuoti perché le richieste sono state riprodotte correttamente.
Tipi
BackgroundSyncPlugin
Una classe che implementa il callback fetchDidFail
del ciclo di vita. Ciò semplifica l'aggiunta di richieste non riuscite a una coda di sincronizzazione in background.
Proprietà
-
costruttore
void
La funzione
constructor
ha il seguente aspetto:(name: string, options?: QueueOptions) => {...}
-
nome
stringa
Per i dettagli sui parametri, consulta la documentazione
workbox-background-sync.Queue
. -
opzioni
QueueOptions (facoltativo)
-
returns
-
Queue
Una classe per gestire l'archiviazione delle richieste non riuscite in IndexedDB e per riprovare in un secondo momento. Tutte le parti del processo di archiviazione e riproduzione sono osservabili tramite callback.
Proprietà
-
costruttore
void
Crea un'istanza di Queue con le opzioni specificate
La funzione
constructor
ha il seguente aspetto:(name: string, options?: QueueOptions) => {...}
-
nome
stringa
Il nome univoco per questa coda. Questo nome deve essere univoco, poiché viene utilizzato per registrare eventi di sincronizzazione e archiviare richieste in IndexedDB specifici per questa istanza. Se viene rilevato un nome duplicato, viene generato un errore.
-
opzioni
QueueOptions (facoltativo)
-
returns
-
-
nome
stringa
-
getAll
void
Restituisce tutte le voci non scadute (per
maxRetentionTime
). Le voci scadute vengono rimosse dalla coda.La funzione
getAll
ha il seguente aspetto:() => {...}
-
returns
Promise<QueueEntry[]>
-
-
popRequest
void
Rimuove e restituisce l'ultima richiesta in coda (insieme al timestamp e agli eventuali metadati). L'oggetto restituito ha il formato:
{request, timestamp, metadata}
.La funzione
popRequest
ha il seguente aspetto:() => {...}
-
returns
Promise<QueueEntry>
-
-
pushRequest
void
Archivia la richiesta passata in IndexedDB (con relativo timestamp ed eventuali metadati) alla fine della coda.
La funzione
pushRequest
ha il seguente aspetto:(entry: QueueEntry) => {...}
-
voce
QueueEntry
-
returns
Promise<void>
-
-
registerSync
void
Registra un evento di sincronizzazione con un tag univoco per questa istanza.
La funzione
registerSync
ha il seguente aspetto:() => {...}
-
returns
Promise<void>
-
-
replayRequests
void
Esamina ogni richiesta in coda e tenta di recuperarla nuovamente. Se il recupero di una qualsiasi richiesta non riesce, viene collocata di nuovo nella stessa posizione nella coda (in modo da registrare un nuovo tentativo per il successivo evento di sincronizzazione).
La funzione
replayRequests
ha il seguente aspetto:() => {...}
-
returns
Promise<void>
-
-
shiftRequest
void
Rimuove e restituisce la prima richiesta in coda (insieme al timestamp e agli eventuali metadati). L'oggetto restituito ha il formato:
{request, timestamp, metadata}
.La funzione
shiftRequest
ha il seguente aspetto:() => {...}
-
returns
Promise<QueueEntry>
-
-
dimensioni
void
Restituisce il numero di voci presenti nella coda. Tieni presente che in questo conteggio sono incluse anche le voci scadute (per
maxRetentionTime
).La funzione
size
ha il seguente aspetto:() => {...}
-
returns
Promessa<numero>
-
-
unshiftRequest
void
Archivia la richiesta passata in IndexedDB (con relativo timestamp ed eventuali metadati) all'inizio della coda.
La funzione
unshiftRequest
ha il seguente aspetto:(entry: QueueEntry) => {...}
-
voce
QueueEntry
-
returns
Promise<void>
-
QueueOptions
Proprietà
-
forceSyncFallback
booleano facoltativo
-
maxRetentionTime
numero facoltativo
-
onSync
OnSyncCallback facoltativo
QueueStore
Una classe per gestire le richieste di archiviazione da una coda in IndexedDB, indicizzata in base al nome della coda per un accesso più semplice.
La maggior parte degli sviluppatori non dovrà accedere direttamente a questo corso, che è esposto a casi d'uso avanzati.
Proprietà
-
costruttore
void
Associa questa istanza a un'istanza Queue, che consente di identificare le voci aggiunte in base al nome della coda.
La funzione
constructor
ha il seguente aspetto:(queueName: string) => {...}
-
queueName
stringa
-
returns
-
-
deleteEntry
void
Elimina la voce relativa all'ID specificato.
ATTENZIONE: questo metodo non garantisce che la voce eliminata appartenga a questa coda (ossia corrisponde al valore
queueName
). Tuttavia, questa limitazione è accettabile, in quanto questa classe non è esposta pubblicamente. Un controllo aggiuntivo renderebbe questo metodo più lento.La funzione
deleteEntry
ha il seguente aspetto:(id: number) => {...}
-
id
numero
-
returns
Promise<void>
-
-
getAll
void
Restituisce tutte le voci dello store corrispondenti a
queueName
.La funzione
getAll
ha il seguente aspetto:() => {...}
-
returns
Promise<QueueStoreEntry[]>
-
-
popEntry
void
Rimuove e restituisce l'ultima voce della coda corrispondente a
queueName
.La funzione
popEntry
ha il seguente aspetto:() => {...}
-
returns
Promise<QueueStoreEntry>
-
-
pushEntry
void
Aggiungi una voce all'ultima voce in coda.
La funzione
pushEntry
ha il seguente aspetto:(entry: UnidentifiedQueueStoreEntry) => {...}
-
voce
UnidentifiedQueueStoreEntry
-
returns
Promise<void>
-
-
shiftEntry
void
Rimuove e restituisce la prima voce in coda corrispondente a
queueName
.La funzione
shiftEntry
ha il seguente aspetto:() => {...}
-
returns
Promise<QueueStoreEntry>
-
-
dimensioni
void
Restituisce il numero di voci nello store corrispondenti a
queueName
.La funzione
size
ha il seguente aspetto:() => {...}
-
returns
Promessa<numero>
-
-
unshiftEntry
void
Prima di inserire una voce nella coda.
La funzione
unshiftEntry
ha il seguente aspetto:(entry: UnidentifiedQueueStoreEntry) => {...}
-
voce
UnidentifiedQueueStoreEntry
-
returns
Promise<void>
-
StorableRequest
Una classe per semplificare la serializzazione e la deserializzazione delle richieste in modo che possano essere archiviate in IndexedDB.
La maggior parte degli sviluppatori non dovrà accedere direttamente a questo corso, che è esposto a casi d'uso avanzati.
Proprietà
-
costruttore
void
Accetta un oggetto di dati della richiesta che può essere utilizzato per creare un
Request
, ma può anche essere archiviato in IndexedDB.La funzione
constructor
ha il seguente aspetto:(requestData: RequestData) => {...}
-
requestData
RequestData
Un oggetto dei dati della richiesta che include
url
più eventuali proprietà pertinenti di [requestInit]https://fetch.spec.whatwg.org/#requestinit
.
-
returns
-
-
clone
void
Crea e restituisce un clone profondo dell'istanza.
La funzione
clone
ha il seguente aspetto:() => {...}
-
returns
-
-
toObject
void
Restituisce un clone profondo dell'oggetto
_requestData
delle istanze.La funzione
toObject
ha il seguente aspetto:() => {...}
-
returns
RequestData
-
-
toRequest
void
Converte questa istanza in una richiesta.
La funzione
toRequest
ha il seguente aspetto:() => {...}
-
returns
Richiesta
-
-
fromRequest
void
Converte un oggetto Request in un oggetto semplice che può essere clonato o strutturato in formato JSON.
La funzione
fromRequest
ha il seguente aspetto:(request: Request) => {...}
-
richiesta
Richiesta
-
returns
Promise<StorableRequest>
-