casella di lavoro-sincronizzazione-in background

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 è:

  1. Carica una pagina e registra il tuo service worker.
  2. 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.
  3. 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
  4. Ora attiva la rete o il server web.
  5. Per forzare un evento sync in anteprima, vai a Chrome DevTools > Application > Service Workers, inserisci il nome tag di workbox-background-sync:<your queue name>, dove <your queue name> dovrebbe essere il nome della coda impostata, quindi fai clic sul pulsante "Sincronizza".

    Esempio del pulsante di sincronizzazione in Chrome DevTools

  6. 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à

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)

  • 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

  • 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.

  • clone

    void

    Crea e restituisce un clone profondo dell'istanza.

    La funzione clone ha il seguente aspetto:

    ()=> {...}

  • 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