Presentamos la recuperación en segundo plano

En el año 2015, presentamos la sincronización en segundo plano, que permite service worker aplazar el trabajo hasta que el usuario tenga conectividad. Esto significa que el usuario podría escribir una presiona Enviar y abandona el sitio sabiendo que el mensaje se enviará, ya sea ahora o tengan conectividad.

Es una función útil, pero requiere que el service worker esté activo durante la recuperar. Eso no es un problema para momentos cortos de trabajo, como enviar un mensaje, pero si la tarea demora demasiado tiempo, el navegador cerrará el service worker; de lo contrario, representa un riesgo para la privacidad del usuario y batería.

¿Qué sucede si necesitas descargar algo que podría tardar mucho tiempo, como una película, un podcast niveles de un juego. Para eso sirve la recuperación en segundo plano.

La recuperación en segundo plano está disponible de forma predeterminada a partir de Chrome 74.

Aquí te mostramos una demostración rápida de dos minutos en la que se muestra el estado tradicional de las cosas, en comparación con el uso de la recuperación en segundo plano:

Prueba la demostración por tu cuenta y explora el código.

Cómo funciona

La recuperación en segundo plano funciona de la siguiente manera:

  1. Le indicas al navegador que realice un grupo de recuperaciones en segundo plano.
  2. El navegador recupera esos elementos y muestra el progreso al usuario.
  3. Una vez que la recuperación se haya completado o falló, el navegador abrirá tu service worker y activará un evento. para contarte lo que pasó. Aquí es donde decides qué hacer con las respuestas, si corresponde.

Si el usuario cierra las páginas de tu sitio después del paso 1, no hay problema, ya que la descarga continuará. Porque la recuperación es muy visible y se puede anular fácilmente, no hay preocupación por la privacidad de de sincronización en segundo plano. Como el service worker no se ejecuta constantemente, no existe la preocupación de que podría abusar del sistema, como la minería de bitcoin en segundo plano.

En algunas plataformas (como Android), es posible que el navegador se cierre después del paso 1, como navegador puede transferir la recuperación al sistema operativo.

Si el usuario inicia la descarga mientras está sin conexión, o se desconecta durante la descarga, la reproducción en segundo plano la recuperación de datos se pausará y reanudará más tarde.

La API

Detección de atributos

Al igual que con cualquier función nueva, debes detectar si el navegador es compatible. Para la Recuperación en segundo plano, es tan simple como:

if ('BackgroundFetchManager' in self) {
  // This browser supports Background Fetch!
}

Cómo iniciar una recuperación en segundo plano

La API principal suspende el registro de un service worker. así que asegúrate de haber registrado primero un service worker. Luego:

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.fetch('my-fetch', ['/ep-5.mp3', 'ep-5-artwork.jpg'], {
    title: 'Episode 5: Interesting things.',
    icons: [{
      sizes: '300x300',
      src: '/ep-5-icon.png',
      type: 'image/png',
    }],
    downloadTotal: 60 * 1024 * 1024,
  });
});

backgroundFetch.fetch toma tres argumentos:

Parámetros
id string
identifica de forma única esta recuperación en segundo plano.

Se rechazará backgroundFetch.fetch si el ID coincide con un fondo existente recuperar.

requests Array<Request|string>
Los objetos que hay que recuperar. Las cadenas se tratarán como URLs y se convertirán en Request a través de new Request(theString).

Puedes recuperar elementos de otros orígenes, siempre que los recursos lo permitan mediante CORS.

Nota: Actualmente, Chrome no admite solicitudes que requieren una solicitud preliminar de CORS.

options Un objeto que puede incluir lo siguiente:
options.title string
Un título para que el navegador muestre junto con el progreso.
options.icons Array<IconDefinition>
Arreglo de objetos con `src`, `size` y `type`.
options.downloadTotal number
El tamaño total de los cuerpos de la respuesta (después de que se descomprimieron con gzip).

Aunque esto es opcional, te recomendamos que lo proporciones. Se usa para contar al usuario qué tan grande es la descarga y brindarle información sobre el progreso. Si no proporcionas el navegador indicará al usuario que el tamaño es desconocido y, como resultado, el usuario puede ser más es probable que anule la descarga.

Si las descargas de recuperación en segundo plano superan el número proporcionado aquí, se anulará. Es no hay problema si la descarga es más pequeña que el downloadTotal, así que, si no si te aseguras de cuál será el total de descargas, es mejor ser precavido.

backgroundFetch.fetch muestra una promesa que se resuelve con un BackgroundFetchRegistration. voy a cubriremos los detalles más adelante. La promesa se rechaza si el usuario inhabilitó las descargas. de los parámetros proporcionados no es válido.

Proporcionar muchas solicitudes para una sola recuperación en segundo plano te permite combinar elementos que sean algo único para el usuario. Por ejemplo, una película puede dividirse en miles de recursos (habitual en MPEG-DASH), y cuentan con recursos adicionales, como imágenes. Un nivel de un juego puede estar repartido en varios Recursos de imagen, audio y JavaScript. Pero para el usuario, es solo "la película" o "el nivel".

Cómo obtener una recuperación en segundo plano existente

Puedes obtener una recuperación en segundo plano existente como la siguiente:

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});

...pasa el id de la recuperación en segundo plano que desees. get muestra undefined si no hay recuperación en segundo plano activa con ese ID.

Una recuperación en segundo plano se considera “activa” desde el momento en que se registra, hasta que tiene éxito, falla o se anula.

Puedes obtener una lista de todas las recuperaciones en segundo plano activas con getIds:

navigator.serviceWorker.ready.then(async (swReg) => {
  const ids = await swReg.backgroundFetch.getIds();
});

Registros de recuperación en segundo plano

Un BackgroundFetchRegistration (bgFetch en los ejemplos anteriores) tiene lo siguiente:

Propiedades
id string
El ID de la recuperación en segundo plano.
uploadTotal number
La cantidad de bytes que se enviarán al servidor.
uploaded number
La cantidad de bytes enviados correctamente.
downloadTotal number
El valor proporcionado cuando se registró la recuperación en segundo plano. cero.
downloaded number
La cantidad de bytes que se recibieron correctamente.

Es posible que este valor disminuya. Por ejemplo, si la conexión se interrumpe y no se puede descargar En este caso, el navegador reiniciará la recuperación de ese recurso desde cero.

result

Uno de los siguientes:

  • "": La recuperación en segundo plano está activa, por lo que aún no hay resultados.
  • "success": la recuperación en segundo plano se realizó correctamente.
  • "failure": No se pudo recuperar el fondo. Este valor solo aparece cuando la recuperación en segundo plano falla por completo, ya que en el navegador no se puede reintentar ni reanudar.
failureReason

Uno de los siguientes:

  • "": La recuperación en segundo plano no falló.
  • "aborted": el usuario anuló la recuperación en segundo plano. Se llamó a abort().
  • "bad-status": Una de las respuestas tenía un estado incorrecto, p.ej., 404
  • "fetch-error": Una de las recuperaciones falló por algún otro motivo; p.ej., CORS, MIX, una respuesta parcial no válida o una falla de red general para una recuperación que no se puede reintentar.
  • "quota-exceeded": Se alcanzó la cuota de almacenamiento durante el segundo plano recuperar.
  • "download-total-exceeded": El valor de "downloadTotal" proporcionado era superada.
recordsAvailable boolean
¿Se puede acceder a las solicitudes o respuestas subyacentes?

Cuando esto sea falso, no se pueden usar match ni matchAll.

Métodos
abort() Muestra Promise<boolean>
Anular la recuperación en segundo plano.

La promesa que se muestra se resuelve con el valor true si la recuperación se anuló con éxito.

matchAll(request, opts) Muestra Promise<Array<BackgroundFetchRecord>>
Obtener las solicitudes y respuestas.

Estos argumentos son los mismos que la caché API Si llamas sin argumentos, se muestra una promesa para todos los registros.

Consulte la siguiente información para obtener más detalles.

match(request, opts) Muestra Promise<BackgroundFetchRecord>
Como se muestra más arriba, pero se resuelve con el primer partido.
Eventos
progress Se activa cuando cualquiera de los valores de uploaded, downloaded, result o Cambio en failureReason.

Seguimiento del progreso

Esto se puede hacer mediante el evento progress. Recuerda que downloadTotal es el valor que o 0 si no proporcionaste ningún valor.

bgFetch.addEventListener('progress', () => {
  // If we didn't provide a total, we can't provide a %.
  if (!bgFetch.downloadTotal) return;

  const percent = Math.round(bgFetch.downloaded / bgFetch.downloadTotal * 100);
  console.log(`Download progress: ${percent}%`);
});

Obtén las solicitudes y respuestas

bgFetch.match('/ep-5.mp3').then(async (record) => {
  if (!record) {
    console.log('No record found');
    return;
  }

  console.log(`Here's the request`, record.request);
  const response = await record.responseReady;
  console.log(`And here's the response`, response);
});

record es un BackgroundFetchRecord y se ve de la siguiente manera:

Propiedades
request Request
La solicitud que se presentó.
responseReady Promise<Response>
La respuesta recuperada.

La respuesta está detrás de una promesa porque es posible que aún no se haya recibido. La promesa se rechazará si la recuperación falla.

Eventos de service worker

Eventos
backgroundfetchsuccess Se recuperó todo correctamente.
backgroundfetchfailure Fallaron una o más de las recuperaciones.
backgroundfetchabort Fallaron una o más recuperaciones.

Esto solo es realmente útil si deseas realizar una limpieza de datos relacionados.

backgroundfetchclick El usuario hizo clic en la IU del progreso de la descarga.

Los objetos de evento tienen lo siguiente:

Propiedades
registration BackgroundFetchRegistration
Métodos
updateUI({ title, icons }) Te permite cambiar el título o los íconos que configuraste inicialmente. Esto es opcional, pero te permite proporcionar más contexto si es necesario. Puedes hacer esto *una vez* durante Eventos backgroundfetchsuccess y backgroundfetchfailure.

Reaccionar ante el éxito o el fracaso

Ya hemos visto el evento progress, pero es útil solo cuando el usuario tiene una página abierta para tu sitio. El principal beneficio de la recuperación en segundo plano es que las opciones siguen funcionando después de que el usuario sale de la o incluso cierra el navegador.

Si la recuperación en segundo plano se completa con éxito, tu service worker recibirá backgroundfetchsuccess será el evento y event.registration será el registro para la recuperación en segundo plano.

Después de este evento, ya no se puede acceder a las solicitudes y respuestas recuperadas, por lo que si deseas y mantenlas, muévelas a algún lugar como la API de Cache.

Como en la mayoría de los eventos de service worker, usa event.waitUntil para que el service worker sepa cuándo ocurre el evento esté completo.

Por ejemplo, en tu service worker:

addEventListener('backgroundfetchsuccess', (event) => {
  const bgFetch = event.registration;

  event.waitUntil(async function() {
    // Create/open a cache.
    const cache = await caches.open('downloads');
    // Get all the records.
    const records = await bgFetch.matchAll();
    // Copy each request/response across.
    const promises = records.map(async (record) => {
      const response = await record.responseReady;
      await cache.put(record.request, response);
    });

    // Wait for the copying to complete.
    await Promise.all(promises);

    // Update the progress notification.
    event.updateUI({ title: 'Episode 5 ready to listen!' });
  }());
});

El error puede haberse reducido a un solo error 404, lo cual puede no haber sido importante para ti, por lo que podría igual vale la pena copiar algunas respuestas a una caché como se muestra arriba.

Reacción al clic

Se puede hacer clic en la IU que muestra el progreso y el resultado de la descarga. El evento backgroundfetchclick en y el service worker te permite reaccionar. Como se muestra más arriba, event.registration será el fondo. recuperar el registro.

Lo más común es abrir una ventana:

addEventListener('backgroundfetchclick', (event) => {
  const bgFetch = event.registration;

  if (bgFetch.result === 'success') {
    clients.openWindow('/latest-podcasts');
  } else {
    clients.openWindow('/download-progress');
  }
});

Recursos adicionales

Corrección: Una versión anterior de este artículo hacía referencia incorrectamente a la recuperación en segundo plano como un "estándar web". Actualmente, la API no se encuentra en la rama estándar. La especificación se puede encontrar en WICG como un borrador del informe del grupo de la comunidad.