sincronización-en segundo plano-de-la-caja de trabajo

Cuando envías datos a un servidor web, a veces las solicitudes fallarán. Puede deberse a que el usuario perdió conectividad o a que el servidor no funciona. En cualquier caso, a menudo querrás volver a intentar enviar las solicitudes más tarde.

La nueva API de BackgroundSync es una solución ideal para este problema. Cuando un service worker detecta que falló una solicitud de red, se puede registrar para recibir un evento sync, que se entrega cuando el navegador considera que se devolvió la conectividad. Ten en cuenta que el evento de sincronización se puede entregar incluso si el usuario abandonó la aplicación, lo que lo hace mucho más eficaz que el método tradicional de reintentar solicitudes con errores.

La sincronización en segundo plano de Workbox se diseñó para facilitar el uso de la API de BackgroundSync y la integración de su uso con otros módulos de Workbox. También implementa una estrategia de resguardo para navegadores que aún no implementan BackgroundSync.

Los navegadores compatibles con la API de BackgroundSync reproducirán automáticamente las solicitudes fallidas en tu nombre en un intervalo administrado por el navegador, que probablemente use una retirada exponencial entre los intentos de repetición. En los navegadores que no admiten de forma nativa la API de BackgroundSync, la sincronización en segundo plano de Workbox intentará volver a reproducirla automáticamente cada vez que se inicie el service worker.

Uso básico

La forma más fácil de usar la sincronización en segundo plano es utilizar Plugin, que pondrá automáticamente en cola las solicitudes con errores y las volverá a intentar cuando se activen los eventos sync futuros.

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 conecta a la devolución de llamada del complemento fetchDidFail y solo se invoca a fetchDidFail si se produce una excepción, probablemente debido a una falla de la red. Esto significa que no se reintentarán las solicitudes si se recibe una respuesta con un estado de error 4xx o 5xx. Si deseas reintentar todas las solicitudes que generan, p.ej., un estado 5xx, puedes hacerlo agregando un complemento fetchDidSucceed a tu estrategia:

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.

Uso avanzado

La sincronización en segundo plano de Workbox también proporciona una clase Queue, de la que puedes crear una instancia y agregarle solicitudes con errores. Las solicitudes erróneas se almacenan en IndexedDB y se vuelven a intentar cuando el navegador considera que se restableció la conectividad (es decir, cuando recibe el evento de sincronización).

Cómo crear una cola

Para crear una cola de sincronización en segundo plano de Workbox, debes construirla con un nombre de cola (que debe ser único de tu origen):

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

const queue = new Queue('myQueueName');

El nombre de la cola se usa como parte del nombre de la etiqueta que el SyncManager global agrega a register(). También se usa como nombre de Object Store para la base de datos IndexedDB.

Agrega una solicitud a la cola

Una vez que hayas creado tu instancia de cola, puedes agregarle solicitudes fallidas. Para agregar una solicitud con errores, invoca el método .pushRequest(). Por ejemplo, el siguiente código detecta las solicitudes que fallan y las agrega a la cola:

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 vez que se agrega a la cola, se vuelve a intentar automáticamente la solicitud cuando el service worker recibe el evento sync (que sucede cuando el navegador considera que se restableció la conectividad). Los navegadores que no admiten la API de BackgroundSync volverán a intentar la cola cada vez que se inicie el service worker. Esto requiere que se ejecute la página que controla el service worker, por lo que no será tan eficaz.

Prueba la sincronización en segundo plano de Workbox

Lamentablemente, probar BackgroundSync es un poco poco intuitivo y difícil por varias razones.

El mejor enfoque para probar tu implementación es hacer lo siguiente:

  1. Carga una página y registra tu service worker.
  2. Apaga la red de tu computadora o el servidor web.
    • NO UTILICE LAS HERRAMIENTAS DE DISPOSITIVOS CHROME SIN CONEXIÓN. La casilla de verificación sin conexión en Herramientas para desarrolladores solo afecta las solicitudes de la página. Las solicitudes de los service worker seguirán en proceso.
  3. Realiza solicitudes de red que deben estar en cola con la sincronización en segundo plano de Workbox.
    • Para verificar que las solicitudes se colocaron en cola, consulta Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests.
  4. Ahora enciende tu red o servidor web.
  5. Para forzar un evento sync temprano, ve a Chrome DevTools > Application > Service Workers, ingresa el nombre de la etiqueta de workbox-background-sync:<your queue name>, donde <your queue name> debe ser el nombre de la cola que configuraste y, luego, haz clic en el botón "Sincronizar".

    Ejemplo del botón Sincronizar en las Herramientas para desarrolladores de Chrome

  6. Deberías ver que las solicitudes de red se procesaron para las solicitudes con errores y que los datos de IndexedDB deberían estar vacíos, ya que las solicitudes se volvieron a reproducir con éxito.

Tipos

BackgroundSyncPlugin

Una clase que implementa la devolución de llamada de ciclo de vida de fetchDidFail. Esto facilita la tarea de agregar solicitudes erróneas a una cola de sincronización en segundo plano.

Propiedades

Queue

Una clase para administrar el almacenamiento de solicitudes con errores en IndexedDB y reintentarlas más tarde. Todas las partes del proceso de almacenamiento y reproducción son observables a través de devoluciones de llamada.

Propiedades

  • constructor

    void

    Crea una instancia de Queue con las opciones determinadas.

    La función constructor se ve de la siguiente manera:

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

    • name

      cadena

      El nombre único de esta cola. Este nombre debe ser único, ya que se usa para registrar eventos de sincronización y almacenar solicitudes en IndexedDB específicas de esta instancia. Se mostrará un error si se detecta un nombre duplicado.

    • Opciones

      QueueOptions opcional

  • name

    cadena

  • getAll

    void

    Muestra todas las entradas que no vencieron (por maxRetentionTime). Las entradas vencidas se quitan de la cola.

    La función getAll se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Promise<QueueEntry[]>

  • popRequest

    void

    Quita y muestra la última solicitud de la cola (junto con su marca de tiempo y los metadatos). El objeto que se muestra toma la forma: {request, timestamp, metadata}.

    La función popRequest se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Promise<QueueEntry>

  • pushRequest

    void

    Almacena la solicitud pasada en IndexedDB (con su marca de tiempo y metadatos) al final de la cola.

    La función pushRequest se ve de la siguiente manera:

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

    • entry.

      QueueEntry

    • resultados

      Promise<void>

  • registerSync

    void

    Registra un evento de sincronización con una etiqueta única para esta instancia.

    La función registerSync se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Promise<void>

  • replayRequests

    void

    Realiza un bucle a cada solicitud en la cola e intenta recuperarla. Si alguna solicitud no se puede volver a recuperar, se vuelve a colocar en la misma posición en la cola (lo que registra un reintento para el siguiente evento de sincronización).

    La función replayRequests se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Promise<void>

  • shiftRequest

    void

    Quita y muestra la primera solicitud de la cola (junto con su marca de tiempo y los metadatos). El objeto que se muestra toma la forma: {request, timestamp, metadata}.

    La función shiftRequest se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Promise<QueueEntry>

  • tamaño

    void

    Muestra la cantidad de entradas presentes en la cola. Ten en cuenta que las entradas vencidas (por maxRetentionTime) también se incluyen en este recuento.

    La función size se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Promesa<number>

  • unshiftRequest

    void

    Almacena la solicitud pasada en IndexedDB (con su marca de tiempo y metadatos) al comienzo de la cola.

    La función unshiftRequest se ve de la siguiente manera:

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

    • entry.

      QueueEntry

    • resultados

      Promise<void>

QueueOptions

Propiedades

  • forceSyncFallback

    booleano opcional

  • maxRetentionTime

    número opcional

  • onSync

    OnSyncCallback opcional

QueueStore

Una clase para administrar las solicitudes de almacenamiento de una cola en IndexedDB, indexada por su nombre de cola para facilitar el acceso.

La mayoría de los desarrolladores no necesitarán acceder a esta clase directamente, ya que se expone en casos de uso avanzados.

Propiedades

  • constructor

    void

    Asocia esta instancia con una instancia de cola, por lo que las entradas agregadas se pueden identificar por su nombre de cola.

    La función constructor se ve de la siguiente manera:

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

    • queueName

      cadena

  • deleteEntry

    void

    Borra la entrada del ID especificado.

    ADVERTENCIA: Este método no garantiza que la entrada borrada pertenezca a esta cola (es decir, que coincida con queueName). Sin embargo, esta limitación es aceptable, ya que esta clase no está expuesta públicamente. Una verificación adicional haría que este método sea más lento de lo necesario.

    La función deleteEntry se ve de la siguiente manera:

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

    • id

      número

    • resultados

      Promise<void>

  • getAll

    void

    Muestra todas las entradas de la tienda que coinciden con queueName.

    La función getAll se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Promise<QueueStoreEntry[]>

  • popEntry

    void

    Quita y muestra la última entrada en la cola que coincide con queueName.

    La función popEntry se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Promise<QueueStoreEntry>

  • pushEntry

    void

    Agrega una entrada al final de la cola.

    La función pushEntry se ve de la siguiente manera:

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

    • entry.

      UnidentifiedQueueStoreEntry

    • resultados

      Promise<void>

  • shiftEntry

    void

    Quita y muestra la primera entrada en la cola que coincide con queueName.

    La función shiftEntry se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Promise<QueueStoreEntry>

  • tamaño

    void

    Muestra la cantidad de entradas en la tienda que coinciden con queueName.

    La función size se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Promesa<number>

  • unshiftEntry

    void

    Antepón una entrada en la cola.

    La función unshiftEntry se ve de la siguiente manera:

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

    • entry.

      UnidentifiedQueueStoreEntry

    • resultados

      Promise<void>

StorableRequest

Una clase que facilita la serialización y deserialización de las solicitudes para que se puedan almacenar en IndexedDB.

La mayoría de los desarrolladores no necesitarán acceder a esta clase directamente, ya que se expone en casos de uso avanzados.

Propiedades

  • constructor

    void

    Acepta un objeto de datos de solicitud que se puede usar para construir una Request, pero también se puede almacenar en IndexedDB.

    La función constructor se ve de la siguiente manera:

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

    • requestData

      RequestData

      Un objeto de datos de solicitud que incluye url y cualquier propiedad relevante de [requestInit]https://fetch.spec.whatwg.org/#requestinit.

  • clone

    void

    Crea y muestra una clonación profunda de la instancia.

    La función clone se ve de la siguiente manera:

    ()=> {...}

  • toObject

    void

    Muestra un clon profundo del objeto _requestData de las instancias.

    La función toObject se ve de la siguiente manera:

    ()=> {...}

    • resultados

      RequestData

  • toRequest

    void

    Convierte esta instancia en una solicitud.

    La función toRequest se ve de la siguiente manera:

    ()=> {...}

    • resultados

      Solicitud

  • fromRequest

    void

    Convierte un objeto Request en un objeto sin formato que se puede clonar de forma estructurada o en cadena de JSON.

    La función fromRequest se ve de la siguiente manera:

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

    • request

      Solicitud