werkbox-achtergrondsynchronisatie

Wanneer u gegevens naar een webserver verzendt, mislukken de verzoeken soms. Het kan zijn omdat de gebruiker de connectiviteit heeft verloren, of omdat de server niet beschikbaar is; in beide gevallen wilt u vaak proberen de verzoeken later opnieuw te verzenden.

De nieuwe BackgroundSync API is een ideale oplossing voor dit probleem. Wanneer een servicemedewerker detecteert dat een netwerkverzoek is mislukt, kan deze zich registreren voor het ontvangen van een sync , die wordt afgeleverd wanneer de browser denkt dat de connectiviteit is hersteld. Houd er rekening mee dat de synchronisatiegebeurtenis zelfs kan worden afgeleverd als de gebruiker de applicatie heeft verlaten , waardoor deze veel effectiever is dan de traditionele methode voor het opnieuw proberen van mislukte verzoeken.

Workbox Background Sync is ontworpen om het gebruik van de BackgroundSync API eenvoudiger te maken en het gebruik ervan met andere Workbox-modules te integreren. Het implementeert ook een fallback-strategie voor browsers die BackgroundSync nog niet implementeren.

Browsers die de BackgroundSync API ondersteunen, zullen mislukte verzoeken automatisch namens u opnieuw afspelen met een interval dat wordt beheerd door de browser , waarbij waarschijnlijk gebruik wordt gemaakt van exponentiële vertraging tussen herhalingspogingen. In browsers die de BackgroundSync API niet standaard ondersteunen, probeert Workbox Background Sync automatisch opnieuw af te spelen wanneer uw servicemedewerker opstart.

Basisgebruik

De eenvoudigste manier om Achtergrondsynchronisatie te gebruiken is door de Plugin te gebruiken die automatisch mislukte verzoeken in de wachtrij zet en deze opnieuw probeert wanneer toekomstige sync worden geactiveerd.

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 haakt in op de fetchDidFail plug-in callback en fetchDidFail wordt alleen aangeroepen als er een uitzondering optreedt, hoogstwaarschijnlijk als gevolg van een netwerkfout. Dit betekent dat verzoeken niet opnieuw worden geprobeerd als er een antwoord wordt ontvangen met de foutstatus 4xx of 5xx . Als u alle verzoeken die resulteren in bijvoorbeeld een 5xx status opnieuw wilt proberen, kunt u dit doen door een fetchDidSucceed -plug-in aan uw strategie toe te voegen :

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.

Geavanceerd gebruik

Workbox Background Sync biedt ook een klasse Queue , waaraan u mislukte verzoeken kunt instantiëren en eraan kunt toevoegen. De mislukte verzoeken worden opgeslagen in IndexedDB en opnieuw geprobeerd wanneer de browser denkt dat de connectiviteit is hersteld (dwz wanneer deze de synchronisatiegebeurtenis ontvangt).

Een wachtrij maken

Om een ​​Workbox Background Sync Queue te maken, moet u deze construeren met een wachtrijnaam (die uniek moet zijn voor uw oorsprong ):

import {Queue} from 'workbox-background-sync';

const queue = new Queue('myQueueName');

De wachtrijnaam wordt gebruikt als onderdeel van de tagnaam die register() -ed krijgt door de globale SyncManager . Het wordt ook gebruikt als de Object Store- naam voor de IndexedDB-database.

Een verzoek aan de wachtrij toevoegen

Nadat u uw Queue-instantie heeft gemaakt, kunt u er mislukte verzoeken aan toevoegen. U voegt een mislukt verzoek toe door de methode .pushRequest() aan te roepen. De volgende code vangt bijvoorbeeld alle aanvragen op die mislukken en voegt deze toe aan de wachtrij:

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());
});

Zodra het verzoek aan de wachtrij is toegevoegd, wordt het automatisch opnieuw geprobeerd wanneer de servicemedewerker de sync ontvangt (wat gebeurt wanneer de browser denkt dat de connectiviteit is hersteld). Browsers die de BackgroundSync API niet ondersteunen, zullen de wachtrij telkens opnieuw proberen wanneer de servicemedewerker wordt opgestart. Hiervoor moet de pagina die de servicemedewerker bestuurt actief zijn, dus het zal niet zo effectief zijn.

Workbox-achtergrondsynchronisatie testen

Helaas is het testen van BackgroundSync om een ​​aantal redenen enigszins onintuïtief en moeilijk.

De beste aanpak om uw implementatie te testen is door het volgende te doen:

  1. Laad een pagina en registreer uw servicemedewerker.
  2. Schakel het netwerk van uw computer uit of schakel uw webserver uit.
    • GEBRUIK CHROME DEVTOOLS NIET OFFLINE. Het offline selectievakje in DevTools heeft alleen invloed op verzoeken van de pagina. Verzoeken van servicemedewerkers blijven binnenkomen.
  3. Maak netwerkverzoeken die in de wachtrij moeten worden geplaatst met Workbox Background Sync.
    • U kunt controleren of de verzoeken in de wachtrij zijn geplaatst door te kijken in Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests
  4. Schakel nu uw netwerk- of webserver in.
  5. Forceer een vroege sync door naar Chrome DevTools > Application > Service Workers te gaan, de tagnaam van workbox-background-sync:<your queue name> in te voeren, waarbij <your queue name> de naam moet zijn van de wachtrij die u hebt ingesteld, en vervolgens door op de knop 'Synchroniseren' te klikken.

    Voorbeeld van de synchronisatieknop in Chrome DevTools

  6. U zou netwerkverzoeken moeten zien doorgaan voor de mislukte verzoeken en de IndexedDB-gegevens zouden nu leeg moeten zijn omdat de verzoeken met succes opnieuw zijn afgespeeld.

Soorten

BackgroundSyncPlugin

Een klasse die de levenscycluscallback fetchDidFail implementeert. Dit maakt het eenvoudiger om mislukte verzoeken toe te voegen aan een wachtrij voor synchronisatie op de achtergrond.

Eigenschappen

Queue

Een klasse voor het beheren van het opslaan van mislukte aanvragen in IndexedDB en het later opnieuw proberen ervan. Alle delen van het opslag- en afspeelproces zijn waarneembaar via callbacks.

Eigenschappen

  • bouwer

    leegte

    Creëert een exemplaar van Queue met de gegeven opties

    De constructor ziet er als volgt uit:

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

    • naam

      snaar

      De unieke naam voor deze wachtrij. Deze naam moet uniek zijn, omdat deze wordt gebruikt om synchronisatiegebeurtenissen te registreren en verzoeken op te slaan in IndexedDB die specifiek zijn voor deze instantie. Er wordt een fout gegenereerd als er een dubbele naam wordt gedetecteerd.

    • opties

      Wachtrijopties optioneel

  • naam

    snaar

  • krijg alles

    leegte

    Retourneert alle vermeldingen die niet zijn verlopen (per maxRetentionTime ). Alle verlopen vermeldingen worden uit de wachtrij verwijderd.

    De getAll functie ziet er als volgt uit:

    () => {...}

    • retourneert

      Beloof<QueueEntry[]>

  • popAanvraag

    leegte

    Verwijdert en retourneert het laatste verzoek in de wachtrij (samen met de tijdstempel en eventuele metagegevens). Het geretourneerde object heeft de vorm: {request, timestamp, metadata} .

    De popRequest functie ziet er als volgt uit:

    () => {...}

    • retourneert

      Belofte<QueueEntry>

  • pushRequest

    leegte

    Slaat het doorgegeven verzoek op in IndexedDB (met zijn tijdstempel en eventuele metagegevens) aan het einde van de wachtrij.

    De pushRequest functie ziet er als volgt uit:

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

    • binnenkomst

      Wachtrijinvoer

    • retourneert

      Beloof <nietig>

  • registerSync

    leegte

    Registreert een synchronisatiegebeurtenis met een tag die uniek is voor deze instantie.

    De registerSync functie ziet er als volgt uit:

    () => {...}

    • retourneert

      Beloof <nietig>

  • herhaalverzoeken

    leegte

    Doorloopt elk verzoek in de wachtrij en probeert het opnieuw op te halen. Als een verzoek niet opnieuw kan worden opgehaald, wordt het teruggezet op dezelfde positie in de wachtrij (wat een nieuwe poging registreert voor de volgende synchronisatiegebeurtenis).

    De replayRequests functie ziet er als volgt uit:

    () => {...}

    • retourneert

      Beloof <nietig>

  • shiftRequest

    leegte

    Verwijdert en retourneert het eerste verzoek in de wachtrij (samen met de tijdstempel en eventuele metagegevens). Het geretourneerde object heeft de vorm: {request, timestamp, metadata} .

    De shiftRequest functie ziet er als volgt uit:

    () => {...}

    • retourneert

      Belofte<QueueEntry>

  • maat

    leegte

    Retourneert het aantal vermeldingen in de wachtrij. Houd er rekening mee dat verlopen vermeldingen (per maxRetentionTime ) ook in deze telling worden opgenomen.

    De size ziet er als volgt uit:

    () => {...}

    • retourneert

      Beloof<nummer>

  • unshiftRequest

    leegte

    Slaat het doorgegeven verzoek op in IndexedDB (met zijn tijdstempel en eventuele metagegevens) aan het begin van de wachtrij.

    De unshiftRequest functie ziet er als volgt uit:

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

    • binnenkomst

      Wachtrijinvoer

    • retourneert

      Beloof <nietig>

QueueOptions

Eigenschappen

  • forceSyncFallback

    Booleaans optioneel

  • maxRetentieTijd

    nummer optioneel

  • onSync

    OnSyncCallback optioneel

QueueStore

Een klasse voor het beheren van het opslaan van aanvragen uit een wachtrij in IndexedDB, geïndexeerd op basis van hun wachtrijnaam voor eenvoudigere toegang.

De meeste ontwikkelaars hebben geen rechtstreekse toegang tot deze klasse nodig; het is beschikbaar voor geavanceerde gebruiksscenario's.

Eigenschappen

  • bouwer

    leegte

    Koppelt dit exemplaar aan een wachtrij-exemplaar, zodat toegevoegde vermeldingen kunnen worden geïdentificeerd aan de hand van hun wachtrijnaam.

    De constructor ziet er als volgt uit:

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

    • wachtrijNaam

      snaar

  • verwijderInvoer

    leegte

    Verwijdert de vermelding voor de opgegeven ID.

    WAARSCHUWING: deze methode garandeert niet dat het verwijderde item tot deze wachtrij behoort (dwz overeenkomt met de queueName ). Maar deze beperking is acceptabel omdat deze klasse niet openbaar wordt gemaakt. Een extra controle zou deze methode langzamer maken dan nodig is.

    De deleteEntry functie ziet er als volgt uit:

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

    • Identiteitskaart

      nummer

    • retourneert

      Beloof <nietig>

  • krijg alles

    leegte

    Retourneert alle vermeldingen in de winkel die overeenkomen met de queueName .

    De getAll functie ziet er als volgt uit:

    () => {...}

    • retourneert

      Beloof<QueueStoreEntry[]>

  • popEntry

    leegte

    Verwijdert en retourneert de laatste vermelding in de wachtrij die overeenkomt met de queueName .

    De popEntry functie ziet er als volgt uit:

    () => {...}

    • retourneert

      Belofte<QueueStoreEntry>

  • pushEntry

    leegte

    Voeg een item als laatste in de wachtrij toe.

    De pushEntry functie ziet er als volgt uit:

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

    • binnenkomst

      Niet-geïdentificeerdeQueueStoreEntry

    • retourneert

      Beloof <nietig>

  • shiftEntry

    leegte

    Verwijdert en retourneert de eerste vermelding in de wachtrij die overeenkomt met de queueName .

    De shiftEntry functie ziet er als volgt uit:

    () => {...}

    • retourneert

      Belofte<QueueStoreEntry>

  • maat

    leegte

    Retourneert het aantal vermeldingen in het archief dat overeenkomt met de queueName .

    De size ziet er als volgt uit:

    () => {...}

    • retourneert

      Beloof<nummer>

  • unshiftEntry

    leegte

    Plaats een vermelding als eerste in de wachtrij.

    De unshiftEntry functie ziet er als volgt uit:

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

    • binnenkomst

      Niet-geïdentificeerdeQueueStoreEntry

    • retourneert

      Beloof <nietig>

StorableRequest

Een klasse waarmee u eenvoudiger aanvragen kunt serialiseren en deserialiseren, zodat ze kunnen worden opgeslagen in IndexedDB.

De meeste ontwikkelaars hebben geen rechtstreekse toegang tot deze klasse nodig; het is beschikbaar voor geavanceerde gebruiksscenario's.

Eigenschappen

  • bouwer

    leegte

    Accepteert een object met aanvraaggegevens die kunnen worden gebruikt om een Request samen te stellen, maar die ook kunnen worden opgeslagen in IndexedDB.

    De constructor ziet er als volgt uit:

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

    • verzoekGegevens

      Gegevens aanvragen

      Een object met aanvraaggegevens dat de url plus eventuele relevante eigenschappen van [requestInit] https://fetch.spec.whatwg.org/#requestinit bevat.

  • kloon

    leegte

    Creëert en retourneert een diepe kloon van de instantie.

    De clone ziet er als volgt uit:

    () => {...}

  • naarBezwaar

    leegte

    Retourneert een diepe kloon van het instance-object _requestData .

    De toObject functie ziet er als volgt uit:

    () => {...}

    • retourneert

      Gegevens aanvragen

  • naarAanvragen

    leegte

    Converteert deze instantie naar een verzoek.

    De toRequest functie ziet er als volgt uit:

    () => {...}

    • retourneert

      Verzoek

  • vanAanvraag

    leegte

    Converteert een Request-object naar een gewoon object dat gestructureerd kan worden gekloond of JSON-stringified.

    De fromRequest functie ziet er als volgt uit:

    (request: Request) => {...}

    • verzoek

      Verzoek