synchronisation en arrière-plan de la boîte de travail

Lorsque vous envoyez des données à un serveur Web, il arrive que les requêtes échouent. Il soit parce que l'utilisateur n'est plus connecté, soit parce que le serveur est en panne. dans les deux cas, vous voudrez souvent essayer d'envoyer les demandes plus tard.

La nouvelle API BackgroundSync est une solution idéale à ce problème. Lorsqu'un service worker détecte qu'un la requête réseau a échoué, il peut s'enregistrer pour recevoir un événement sync, qui est livré lorsque le navigateur pense que la connectivité est rétablie. Notez que l'événement de synchronisation peut être envoyé même si l'utilisateur a quitté le application, ce qui le rend beaucoup plus efficace que la méthode traditionnelle Nouvelle tentative de requêtes ayant échoué.

La synchronisation en arrière-plan de Workbox est conçue pour faciliter l'utilisation API BackgroundSync et intégrer son utilisation à d'autres modules Workbox. Il met également en œuvre une stratégie de remplacement pour les navigateurs qui ne l'ont pas encore implémenté. BackgroundSync.

Les navigateurs compatibles avec l'API BackgroundSync relancent automatiquement la lecture des échecs en votre nom un intervalle géré par le navigateur, probablement un intervalle exponentiel entre les tentatives de relecture. Dans les navigateurs ne sont pas compatibles de manière native avec l'API BackgroundSync, la synchronisation en arrière-plan de Workbox tente automatiquement une relecture chaque fois que votre service worker démarre.

Utilisation de base

Le moyen le plus simple d'utiliser la synchronisation en arrière-plan est d'utiliser le Plugin qui Mettez automatiquement en file d'attente les requêtes ayant échoué et réessayez lors sync sont 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 rejoint la Rappel de plug-in fetchDidFail fetchDidFail n'est appelé que si une exception est générée, probablement en raison de à une défaillance du réseau. Cela signifie que les requêtes ne seront pas relancées en cas de que vous avez reçue avec État d'erreur 4xx ou 5xx. Si vous souhaitez relancer toutes les requêtes qui aboutissent, par exemple un état 5xx, vous pouvez le faire Ajouter 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

Workbox Background Sync fournit également une classe Queue, que vous pouvez instancier et y ajouter les requêtes ayant échoué. Les requêtes ayant échoué sont stockées dans IndexedDB et font l'objet de nouvelles tentatives lorsque le navigateur estime que la connectivité est rétablie (par exemple, lors de la réception de l'événement de synchronisation).

Créer une file d'attente

Pour créer une file d'attente de synchronisation en arrière-plan de la boîte de travail, vous devez la construire avec un nom de file d'attente (qui doit être unique à votre origin):

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 register() éditions par le monde SyncManager Il est également utilisé comme Nom du magasin d'objets 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 les 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 ayant échoué 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 est automatiquement relancée lorsque le service worker reçoit l'événement sync (qui se produit lorsque le navigateur pense que la connectivité est rétablie). Les navigateurs qui n'acceptent pas le L'API BackgroundSync relance la file d'attente chaque fois que le service worker a démarré. Pour ce faire, la page qui contrôle le service worker doit être en cours d'exécution, donc ce ne sera pas aussi efficace.

Tester la synchronisation en arrière-plan de la boîte de travail

Malheureusement, les tests de BackgroundSync sont difficiles et peu intuitifs. pour plusieurs raisons.

Pour tester votre implémentation, la meilleure approche consiste à procéder comme suit:

  1. Chargez une page et enregistrez votre service worker.
  2. 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 Les outils de développement n'affectent que les requêtes provenant de la page. Requêtes de service workers va continuer de s'exécuter.
  3. Effectuez des requêtes réseau qui doivent être mises en file d'attente avec la synchronisation en arrière-plan de Workbox.
    • Vous pouvez vérifier que les requêtes ont été mises en file d'attente en consultant Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
  4. Activez maintenant votre réseau ou votre serveur Web.
  5. Forcer un événement sync anticipé en accédant à Chrome DevTools > Application > Service Workers, en saisissant le nom de balise de workbox-background-sync:<your queue name>, où <your queue name> devrait être le nom de la file d'attente définie, puis en cliquant sur le bouton "Synchroniser" .

    Exemple de bouton de synchronisation dans les outils pour les développeurs Chrome

  6. Vous devriez voir les requêtes réseau aboutir pour les requêtes ayant échoué et les données IndexedDB devraient maintenant être vides puisque les requêtes ont été relue avec succès.

Types

BackgroundSyncPlugin

Une classe implémentant le rappel de cycle de vie d'une fetchDidFail. Ainsi, plus facile d'ajouter les requêtes ayant échoué à une file d'attente de synchronisation en arrière-plan.

Propriétés

Queue

Une classe permettant de gérer le stockage des requêtes ayant échoué dans IndexedDB et de les relancer plus tard. Toutes les parties du processus de stockage et de relecture sont observables via .

Propriétés

  • constructor

    vide

    Crée une instance de Queue avec les options données.

    La fonction constructor se présente comme suit:

    (name: string, options?: QueueOptions) => {...}

    • nom

      chaîne

      Nom unique de cette file d'attente. Ce nom doit être unique, car il est utilisé pour enregistrer des événements de synchronisation et stocker les requêtes dans IndexedDB spécifiques à cette instance. Une erreur est générée si si un nom en double est détecté.

    • options

      QueueOptions facultatif

  • nom

    chaîne

  • getAll

    vide

    Renvoie toutes les entrées qui n'ont pas expiré (par maxRetentionTime). Les entrées expirées sont supprimées de la file d'attente.

    La fonction getAll se présente comme suit:

    () => {...}

    • retours

      Promise&lt;QueueEntry[]&gt;

  • popRequest

    vide

    Supprime et renvoie la dernière requête de la file d'attente (ainsi que ses l'horodatage et les 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&lt;QueueEntry&gt;

  • pushRequest

    vide

    Stocke la requête transmise dans IndexedDB (avec son code temporel et tout métadonnées) à la fin de la file d'attente.

    La fonction pushRequest se présente comme suit:

    (entry: QueueEntry) => {...}

    • entry

      QueueEntry

    • retours

      Promesse<void>

  • registerSync

    vide

    Enregistre un événement de synchronisation avec un tag propre à cette instance.

    La fonction registerSync se présente comme suit:

    () => {...}

    • retours

      Promesse<void>

  • replayRequests

    vide

    Elle parcourt chaque requête de la file d'attente et tente de la récupérer à nouveau. Si une requête échoue de nouveau, elle est remise à la même position dans la file d'attente (qui enregistre une nouvelle tentative pour l'événement de synchronisation suivant).

    La fonction replayRequests se présente comme suit:

    () => {...}

    • retours

      Promesse<void>

  • shiftRequest

    vide

    Supprime et renvoie la première requête de la file d'attente (avec ses l'horodatage et les 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&lt;QueueEntry&gt;

  • taille

    vide

    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 décompte.

    La fonction size se présente comme suit:

    () => {...}

    • retours

      Promise&lt;number&gt;

  • unshiftRequest

    vide

    Stocke la requête transmise dans IndexedDB (avec son code temporel et tout métadonnées) au début de la file d'attente.

    La fonction unshiftRequest se présente comme suit:

    (entry: QueueEntry) => {...}

    • entry

      QueueEntry

    • retours

      Promesse<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és par nom de file d'attente pour y accéder plus facilement.

La plupart des développeurs n'auront pas besoin d'accéder directement à cette classe. il est exposé pour les cas d'utilisation avancés.

Propriétés

  • constructor

    vide

    Associe cette instance à une instance Queue, de sorte que les entrées ajoutées puissent être identifié par son nom de file d'attente.

    La fonction constructor se présente comme suit:

    (queueName: string) => {...}

    • queueName

      chaîne

  • deleteEntry

    vide

    Supprime l'entrée correspondant à l'identifiant donné.

    AVERTISSEMENT: Cette méthode ne garantit pas que l'entrée supprimée appartient à cette (correspond à l'queueName). Mais cette limitation est acceptable car ce cours n'est pas visible publiquement. Une vérification supplémentaire permettrait cette méthode plus lentement qu'elle ne doit l'être.

    La fonction deleteEntry se présente comme suit:

    (id: number) => {...}

    • id

      Nombre

    • retours

      Promesse<void>

  • getAll

    vide

    Renvoie toutes les entrées du magasin correspondant à queueName.

    La fonction getAll se présente comme suit:

    () => {...}

    • retours

      Promise&lt;QueueStoreEntry[]&gt;

  • popEntry

    vide

    Supprime et renvoie la dernière entrée de la file d'attente correspondant à queueName.

    La fonction popEntry se présente comme suit:

    () => {...}

    • retours

      Promise&lt;QueueStoreEntry&gt;

  • pushEntry

    vide

    Ajoute une entrée en dernier dans la file d'attente.

    La fonction pushEntry se présente comme suit:

    (entry: UnidentifiedQueueStoreEntry) => {...}

    • entry

      UnidentifiedQueueStoreEntry

    • retours

      Promesse<void>

  • shiftEntry

    vide

    Supprime et renvoie la première entrée de la file d'attente correspondant à queueName.

    La fonction shiftEntry se présente comme suit:

    () => {...}

    • retours

      Promise&lt;QueueStoreEntry&gt;

  • taille

    vide

    Renvoie le nombre d'entrées dans le magasin correspondant à queueName.

    La fonction size se présente comme suit:

    () => {...}

    • retours

      Promise&lt;number&gt;

  • unshiftEntry

    vide

    Ajoutez une entrée au début de la file d'attente.

    La fonction unshiftEntry se présente comme suit:

    (entry: UnidentifiedQueueStoreEntry) => {...}

    • entry

      UnidentifiedQueueStoreEntry

    • retours

      Promesse<void>

StorableRequest

Une classe pour faciliter la sérialisation et la désérialisation des requêtes afin qu'elles peuvent être stockées dans IndexedDB.

La plupart des développeurs n'auront pas besoin d'accéder directement à cette classe. il est exposé pour les cas d'utilisation avancés.

Propriétés

  • constructor

    vide

    Accepte un objet de données de requête pouvant être utilisé pour construire un Request, mais peut également être stocké dans IndexedDB.

    La fonction constructor se présente comme suit:

    (requestData: RequestData) => {...}

    • requestData

      RequestData

      Un objet de données de requête qui inclut le url, ainsi que toutes les propriétés pertinentes de [requestInit]https://fetch.spec.whatwg.org/#requestinit

  • clone

    vide

    Crée et affiche un clone profond de l'instance.

    La fonction clone se présente comme suit:

    () => {...}

  • toObject

    vide

    Renvoie un clone profond de l'objet d'instances _requestData.

    La fonction toObject se présente comme suit:

    () => {...}

    • retours

      RequestData

  • toRequest

    vide

    Convertit cette instance en requête.

    La fonction toRequest se présente comme suit:

    () => {...}

    • retours

      Requête

  • fromRequest

    vide

    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