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:
- Carga una página y registra tu service worker.
- 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.
- 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
.
- Para verificar que las solicitudes se colocaron en cola, consulta
- Ahora enciende tu red o servidor web.
Para forzar un evento
sync
temprano, ve aChrome DevTools > Application > Service Workers
, ingresa el nombre de la etiqueta deworkbox-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".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
-
constructor
void
La función
constructor
se ve de la siguiente manera:(name: string, options?: QueueOptions) => {...}
-
name
cadena
Consulta la documentación de
workbox-background-sync.Queue
para obtener detalles de los parámetros. -
Opciones
QueueOptions opcional
-
resultados
-
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
-
resultados
-
-
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
-
resultados
-
-
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
.
-
resultados
-
-
clone
void
Crea y muestra una clonación profunda de la instancia.
La función
clone
se ve de la siguiente manera:() => {...}
-
resultados
-
-
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
-
resultados
Promise<StorableRequest>
-