Cómo reintentar solicitudes cuando vuelves a estar en línea

Cuando realizas solicitudes a un servidor web, existe la posibilidad de que se produzcan fallas. Podría deberse a que el usuario perdió la conectividad o a que el servidor remoto no funciona.

Si bien esta documentación se centró principalmente en el manejo de solicitudes GET en un service worker, pueden entrar en juego otros métodos como POST, PUT o DELETE. Estos métodos a menudo se usan para comunicarse con las APIs de backend a fin de proporcionar datos a una app web. Cuando estas solicitudes fallan en ausencia de un service worker, el usuario debe volver a intentarlo manualmente cuando esté de nuevo en línea, y eso no es algo que los usuarios siempre recuerden hacer.

Si tu aplicación se describe de esta manera, y si hay un service worker en la combinación, lo ideal sería que intentes enviar de nuevo las solicitudes fallidas cuando el usuario vuelva a estar en línea. La API de BackgroundSync ofrece una solución a este problema. Cuando un service worker detecta una solicitud de red con errores, se puede registrar para recibir un evento sync cuando el navegador detecte que se devolvió la conectividad. El evento sync se puede entregar incluso si el usuario salió de la página que lo registró, lo que lo hace más eficaz que otros métodos para reintentar solicitudes fallidas.

Workbox abstrae esta API con el módulo workbox-background-sync, lo que facilita el uso de la API de BackgroundSync con otros módulos de Workbox. También implementa una estrategia de resguardo para los navegadores que aún no admiten BackgroundSync.

Uso básico

BackgroundSyncPlugin se exporta desde el módulo workbox-background-sync y se puede usar para poner en cola las solicitudes con errores y reintentarlas cuando se activen 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]
  }),
  // An optional third parameter specifies the request method
  'POST'
);

Aquí, BackgroundSyncPlugin se aplica a una ruta que coincide con las solicitudes POST con una ruta de API que recupera datos JSON. Si el usuario está sin conexión, BackgroundSyncPlugin reintentará la solicitud cuando vuelva a estar en línea, pero solo durante un día como máximo.

Uso avanzado

workbox-background-sync también proporciona una clase Queue, en la que puedes crear instancias y agregarles solicitudes con errores. Al igual que con BackgroundSyncPlugin, las solicitudes fallidas se almacenan en IndexedDB y se prueban cuando el navegador considera que se restableció la conectividad.

Crear una cola

Para crear una cola, crea una instancia del objeto Queue con una cadena que represente el nombre de la cola:

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 crea el método register() proporcionado por el SyncManager global. También es el nombre que se usa para el almacén de objetos que proporciona la base de datos IndexedDB.

Agrega solicitudes a la cola

Después de crear la instancia Queue, puedes agregarle solicitudes fallidas con el método pushRequest():

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 agregan a la cola, las solicitudes se vuelven a intentar automáticamente cuando el service worker recibe el evento sync porque el navegador considera que la red está disponible nuevamente. Los navegadores que no admiten la API de BackgroundSync volverán a intentar la solicitud cada vez que se inicie el service worker. Esta es una forma menos eficaz de reintentar una solicitud con errores, pero se trata de un método alternativo.

Probando workbox-background-sync

Probar el comportamiento de la sincronización en segundo plano puede ser complicado, pero se puede hacer en las Herramientas para desarrolladores de Chrome. El mejor enfoque actual es más o menos así:

  1. Carga una página que registre tu service worker.
  2. Desactiva la conexión de red de la computadora o el servidor web. No uses el botón de activación sin conexión en las Herramientas para desarrolladores de Chrome. La casilla de verificación sin conexión solo afecta las solicitudes de la página, pero las solicitudes del service worker se seguirán procesando.
  3. Realiza solicitudes de red que deben estar en cola con workbox-background-sync. Para verificar las solicitudes que se pusieron en cola, consulta Chrome DevTools > Application > IndexedDB > workbox-background-sync > requests.
  4. Ahora puedes restablecer la conectividad de red o volver a activar el servidor web.
  5. Fuerza un evento de sync temprano. Para ello, ve a Chrome DevTools > Application > Service Workers. Ingresa el nombre de la etiqueta de workbox-background-sync:<your queue name>, en el que <your queue name> es el nombre de la cola que configuraste.
  6. Haz clic en el botón "Sincronizar".
    Captura de pantalla de la utilidad de sincronización en segundo plano en el panel de aplicaciones de Herramientas para desarrolladores de Chrome. El evento de sincronización se especifica en una cola de &quot;myQueueName&quot; para el módulo &quot;workbox-background-sync&quot;.
  7. Ahora deberías ver que se reintentaron y se procesaron las solicitudes de red que fallaron anteriormente. Como resultado, el almacén de IndexedDB debería estar vacío, ya que las solicitudes se volvieron a reproducir correctamente.

Conclusión

Usar workbox-background-sync para reintentar las solicitudes de red fallidas puede ser una excelente manera de mejorar la experiencia del usuario y la confiabilidad de tu app, como permitir que vuelvan a enviar solicitudes a la API fallidas para no perder los datos que querían enviar a tu API. También se puede utilizar para llenar los vacíos en tus propios datos, como las estadísticas. De hecho, el módulo workbox-google-analytics usa workbox-background-sync de forma interna para reintentar las solicitudes fallidas y enviar datos a Google Analytics.

Cualquiera que sea tu caso de uso, workbox-background-sync simplifica este tipo de tarea, lo que mejora tu experiencia de desarrollador y te brinda más oportunidades de optimizar la experiencia del usuario y la funcionalidad de tu aplicación web.