Lorsque vous envoyez des données à un serveur Web, les requêtes peuvent parfois échouer. Cela peut être dû au fait que l'utilisateur a perdu la connectivité ou que le serveur est en panne. Dans les deux cas, vous pouvez réessayer d'envoyer les requêtes plus tard.
La nouvelle API BackgroundSync est une solution idéale à ce problème. Lorsqu'un service worker détecte l'échec d'une requête réseau, il peut s'inscrire pour recevoir un événement sync
, qui est envoyé lorsque le navigateur pense que la connectivité est renvoyée.
Notez que l'événement de synchronisation peut être diffusé même si l'utilisateur a quitté l'application, ce qui est beaucoup plus efficace que la méthode traditionnelle qui consiste à relancer les requêtes ayant échoué.
La synchronisation en arrière-plan de Workbox est conçue pour faciliter l'utilisation de l'API BackgroundSync et l'intégrer à d'autres modules Workbox. Elle implémente également une stratégie de remplacement pour les navigateurs qui n'implémentent pas encore BackgroundSync.
Les navigateurs compatibles avec l'API BackgroundSync relancent automatiquement les requêtes ayant échoué en votre nom à un intervalle géré par le navigateur, probablement à l'aide d'un intervalle exponentiel entre les tentatives. Dans les navigateurs qui ne sont pas compatibles de manière native avec l'API BackgroundSync, Workbox Background Sync tente automatiquement de la relancer au démarrage du service worker.
Utilisation de base
Le moyen le plus simple d'utiliser la synchronisation en arrière-plan consiste à utiliser Plugin
, qui mettra automatiquement en file d'attente les requêtes ayant échoué et les relancera lorsque de futurs événements sync
seront déclenchés.
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
se connecte au rappel du plug-in fetchDidFail
, et fetchDidFail
n'est appelé que si une exception est générée, très probablement en raison d'une défaillance du réseau. Cela signifie que les requêtes ne seront pas relancées si une réponse présente l'état d'erreur 4xx
ou 5xx
.
Si vous souhaitez relancer toutes les requêtes qui aboutissent, par exemple à l'état 5xx
, vous pouvez le faire en ajoutant un plug-in fetchDidSucceed
à votre stratégie:
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.
Utilisation avancée
La synchronisation en arrière-plan de Workbox fournit également une classe Queue
, à laquelle vous pouvez instancier et ajouter les requêtes ayant échoué. Les requêtes ayant échoué sont stockées dans IndexedDB et font l'objet d'une nouvelle tentative lorsque le navigateur pense que la connectivité a été restaurée (c'est-à-dire lorsqu'il reçoit l'événement de synchronisation).
Créer une file d'attente
Pour créer une file d'attente de synchronisation en arrière-plan d'une boîte de travail, vous devez la construire avec un nom de file d'attente (qui doit être unique à votre origine):
import {Queue} from 'workbox-background-sync';
const queue = new Queue('myQueueName');
Le nom de la file d'attente est utilisé dans le nom du tag qui est ajouté à register()
par le SyncManager
global. Il est également utilisé comme nom de magasin d'objets pour la base de données IndexedDB.
Ajouter une requête à la file d'attente
Une fois que vous avez créé votre instance Queue, vous pouvez y ajouter des requêtes ayant échoué.
Pour ajouter une requête ayant échoué, appelez la méthode .pushRequest()
. Par exemple, le code suivant détecte toutes les requ��tes qui échouent et les ajoute à la file d'attente:
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());
});
Une fois ajoutée à la file d'attente, la requête fait automatiquement l'objet d'une nouvelle tentative lorsque le service worker reçoit l'événement sync
(qui se produit lorsque le navigateur pense que la connectivité est restaurée). Les navigateurs qui ne sont pas compatibles avec l'API BackgroundSync relancent la file d'attente à chaque démarrage du service worker. Cette approche nécessite l'exécution de la page contrôlant le service worker. Elle ne sera donc pas aussi efficace.
Test de la synchronisation en arrière-plan de la boîte de travail
Malheureusement, tester BackgroundSync est quelque peu peu intuitif et difficile pour plusieurs raisons.
La meilleure approche pour tester votre implémentation consiste à procéder comme suit:
- Chargez une page et enregistrez votre service worker.
- Désactivez le réseau de votre ordinateur ou votre serveur Web.
- N'UTILISEZ PAS CHROME DEVTOOLS HORS CONNEXION. La case à cocher hors connexion dans DevTools n'affecte que les requêtes provenant de la page. Les requêtes de service worker continueront d'être traitées.
- Effectuez des requêtes réseau qui doivent être placées en file d'attente à l'aide de la synchronisation en arrière-plan Workbox.
- Vous pouvez vérifier que les requêtes ont été mises en file d'attente dans
Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
.
- Vous pouvez vérifier que les requêtes ont été mises en file d'attente dans
- Activez maintenant votre réseau ou votre serveur Web.
Forcez un événement
sync
anticipé en accédant àChrome DevTools > Application > Service Workers
, en saisissant le nom de baliseworkbox-background-sync:<your queue name>
, où<your queue name>
doit être le nom de la file d'attente que vous avez définie, puis en cliquant sur le bouton "Synchroniser".Vous devriez voir les requêtes réseau aboutir pour les requêtes ayant échoué et les données IndexedDB devraient être vides puisque les requêtes ont bien été rejouées.
Types
BackgroundSyncPlugin
Une classe implémentant le rappel de cycle de vie fetchDidFail
. Il est ainsi plus facile d'ajouter les requêtes ayant échoué à une file d'attente de synchronisation en arrière-plan.
Propriétés
-
constructor
void
La fonction
constructor
se présente comme suit :(name: string, options?: QueueOptions) => {...}
-
name
chaîne
Pour en savoir plus sur les paramètres, consultez la documentation sur
workbox-background-sync.Queue
. -
options
QueueOptions facultatif
-
retours
-
Queue
Une classe permettant de gérer le stockage des requêtes ayant échoué dans IndexedDB et de les réessayer ultérieurement. Toutes les parties du processus de stockage et de relecture sont observables via des rappels.
Propriétés
-
constructor
void
Crée une instance de Queue avec les options données.
La fonction
constructor
se présente comme suit :(name: string, options?: QueueOptions) => {...}
-
name
chaîne
Nom unique de cette file d'attente. Ce nom doit être unique, car il permet d'enregistrer des événements de synchronisation et de stocker des requêtes dans IndexedDB spécifiques à cette instance. Une erreur est générée si un nom en double est détecté.
-
options
QueueOptions facultatif
-
retours
-
-
name
chaîne
-
getAll
void
Renvoie toutes les entrées qui n'ont pas expiré (par
maxRetentionTime
). Toutes les entrées expirées sont supprimées de la file d'attente.La fonction
getAll
se présente comme suit :() => {...}
-
retours
Promise<QueueEntry[]>
-
-
popRequest
void
Supprime et renvoie la dernière requête de la file d'attente (ainsi que son horodatage et ses métadonnées). L'objet renvoyé se présente sous la forme suivante :
{request, timestamp, metadata}
.La fonction
popRequest
se présente comme suit :() => {...}
-
retours
Promise<QueueEntry>
-
-
pushRequest
void
Stocke la requête transmise dans IndexedDB (avec son horodatage et ses métadonnées) à la fin de la file d'attente.
La fonction
pushRequest
se présente comme suit :(entry: QueueEntry) => {...}
-
entrée
QueueEntry
-
retours
Promise<void>
-
-
registerSync
void
Enregistre un événement de synchronisation avec un tag propre à cette instance.
La fonction
registerSync
se présente comme suit :() => {...}
-
retours
Promise<void>
-
-
replayRequests
void
Elle parcourt chaque requête de la file d'attente et tente de la récupérer à nouveau. Si la récupération d'une requête échoue, elle est remise à la même position dans la file d'attente (ce qui enregistre une nouvelle tentative pour le prochain événement de synchronisation).
La fonction
replayRequests
se présente comme suit :() => {...}
-
retours
Promise<void>
-
-
shiftRequest
void
Supprimer et renvoyer la première requête de la file d'attente (avec son horodatage et ses métadonnées) L'objet renvoyé se présente sous la forme suivante :
{request, timestamp, metadata}
.La fonction
shiftRequest
se présente comme suit :() => {...}
-
retours
Promise<QueueEntry>
-
-
taille
void
Renvoie le nombre d'entrées présentes dans la file d'attente. Notez que les entrées expirées (par
maxRetentionTime
) sont également incluses dans ce total.La fonction
size
se présente comme suit :() => {...}
-
retours
Promesse<number>
-
-
unshiftRequest
void
Stocke la requête transmise dans IndexedDB (avec son horodatage et ses métadonnées) au début de la file d'attente.
La fonction
unshiftRequest
se présente comme suit :(entry: QueueEntry) => {...}
-
entrée
QueueEntry
-
retours
Promise<void>
-
QueueOptions
Propriétés
-
forceSyncFallback
Booléen facultatif
-
maxRetentionTime
numéro facultatif
-
onSync
OnSyncCallback facultatif
QueueStore
Une classe permettant de gérer les requêtes de stockage d'une file d'attente dans IndexedDB, indexées par leur nom, pour en faciliter l'accès.
La plupart des développeurs n'ont pas besoin d'accéder directement à cette classe, car elle est exposée pour les cas d'utilisation avancés.
Propriétés
-
constructor
void
Associe cette instance à une instance Queue, de sorte que les entrées ajoutées puissent être identifiées par leur nom de file d'attente.
La fonction
constructor
se présente comme suit :(queueName: string) => {...}
-
queueName
chaîne
-
retours
-
-
deleteEntry
void
Supprime l'entrée correspondant à l'identifiant donné.
AVERTISSEMENT: Cette méthode ne garantit pas que l'entrée supprimée appartient à cette file d'attente (c'est-à-dire qu'elle correspond à
queueName
). Toutefois, cette limitation est acceptable, car cette classe n'est pas exposée publiquement. Une vérification supplémentaire rendrait cette méthode plus lente qu'elle ne devrait.La fonction
deleteEntry
se présente comme suit :(id: number) => {...}
-
id
number
-
retours
Promise<void>
-
-
getAll
void
Renvoie toutes les entrées du magasin correspondant à
queueName
.La fonction
getAll
se présente comme suit :() => {...}
-
retours
Promise<QueueStoreEntry[]>
-
-
popEntry
void
Supprimer et renvoyer la dernière entrée de la file d'attente correspondant à
queueName
.La fonction
popEntry
se présente comme suit :() => {...}
-
retours
Promise<QueueStoreEntry>
-
-
pushEntry
void
Ajoute une entrée en dernier dans la file d'attente.
La fonction
pushEntry
se présente comme suit :(entry: UnidentifiedQueueStoreEntry) => {...}
-
entrée
UnidentifiedQueueStoreEntry
-
retours
Promise<void>
-
-
shiftEntry
void
Supprimer et renvoyer la première entrée de la file d'attente correspondant à
queueName
.La fonction
shiftEntry
se présente comme suit :() => {...}
-
retours
Promise<QueueStoreEntry>
-
-
taille
void
Renvoie le nombre d'entrées du magasin correspondant à
queueName
.La fonction
size
se présente comme suit :() => {...}
-
retours
Promesse<number>
-
-
unshiftEntry
void
Ajoutez un préfixe à une entrée dans la file d'attente.
La fonction
unshiftEntry
se présente comme suit :(entry: UnidentifiedQueueStoreEntry) => {...}
-
entrée
UnidentifiedQueueStoreEntry
-
retours
Promise<void>
-
StorableRequest
Classe permettant de faciliter la sérialisation et la désérialisation des requêtes afin qu'elles puissent être stockées dans IndexedDB.
La plupart des développeurs n'ont pas besoin d'accéder directement à cette classe, car elle est exposée pour les cas d'utilisation avancés.
Propriétés
-
constructor
void
Accepte un objet de données de requête qui peut être utilisé pour construire un
Request
, mais qui peut également être stocké dans IndexedDB.La fonction
constructor
se présente comme suit :(requestData: RequestData) => {...}
-
requestData
RequestData
Objet des données de requête qui inclut
url
ainsi que toutes les propriétés pertinentes de [requestInit]https://fetch.spec.whatwg.org/#requestinit
.
-
retours
-
-
clone
void
Crée et affiche un clone profond de l'instance.
La fonction
clone
se présente comme suit :() => {...}
-
retours
-
-
toObject
void
Renvoie un clone profond de l'objet
_requestData
des instances.La fonction
toObject
se présente comme suit :() => {...}
-
retours
RequestData
-
-
toRequest
void
Convertit cette instance en requête.
La fonction
toRequest
se présente comme suit :() => {...}
-
retours
Requête
-
-
fromRequest
void
Convertit un objet Request en un objet brut pouvant être structuré, cloné ou concaténé au format JSON.
La fonction
fromRequest
se présente comme suit :(request: Request) => {...}
-
request
Requête
-
retours
Promise<StorableRequest>
-