Presentamos la sincronización en segundo plano

Jake Archibald
Jake Archibald

La sincronización en segundo plano es una nueva API web que te permite diferir acciones hasta que el usuario tenga una conectividad estable. Esto garantiza que lo que el usuario desea enviar se envíe realmente.

El problema

Internet es un gran lugar para perder el tiempo. Sin perder tiempo en Internet, no sabríamos que a los gatos no les gustan las flores, a los camaleones les encantan las burbujas ni que nuestro propio Eric Bidelman es un héroe del putt golf de fines de los 90.

Pero a veces, solo a veces, no buscamos perder tiempo. La experiencia del usuario deseada se parece más a esto:

  1. Teléfono fuera del bolsillo
  2. Lograr un objetivo menor.
  3. Teléfono de vuelta en el bolsillo.
  4. Reanudar vida.

Lamentablemente, esta experiencia se ve interrumpida con frecuencia por la mala conectividad. A todos nos ha pasado. Estás mirando una pantalla blanca o una pantalla giratoria, y sabes que deberías darlo por vencido y seguir con tu vida, pero le das 10 segundos más por si acaso. ¿Después de esos 10 segundos? Nada.

Pero ¿por qué rendirnos ahora? Ya has invertido tiempo, así que irte sin nada sería un desperdicio, así que puedes seguir esperando. A esta altura, quieres renunciar, pero sabes que, en cuanto lo haces, es el segundo antes de que todo se haya cargado si solo hubieras esperado.

Los service worker resuelven la etapa de carga de la página, ya que te permiten entregar contenido desde una caché. Pero ¿qué ocurre cuando la página necesita enviar algo al servidor?

En este momento, si el usuario presiona "Enviar" en un mensaje, tiene que mirar un ícono giratorio hasta que finalice. Si intentan salir de la pestaña o salir de ella, usamos onbeforeunload para mostrar un mensaje como “No, necesito que mires este ícono giratorio un poco más. Perdón”. Si el usuario no tiene conexión, le decimos "Lo sentimos, debes volver más tarde y volver a intentarlo".

Esto es basura. La sincronización en segundo plano te permite hacer mejor las cosas.

La solución

En el siguiente video, se muestra Emojoy, una demostración de chat solo con emojis. Es una app web progresiva y funciona primero sin conexión. La app usa notificaciones y mensajes push, además de la sincronización en segundo plano.

Si el usuario intenta enviar un mensaje cuando no tiene conectividad, por suerte, el mensaje se enviará en segundo plano una vez que tenga conectividad.

A partir de marzo de 2016, la sincronización en segundo plano está disponible en Chrome a partir de la versión 49. Sigue los pasos que se indican a continuación para ver cómo funciona:

  1. Abre Emojoy.
  2. Desconectarte (ya sea usando el modo de avión o visita tu jaula de Faraday local).
  3. Escribe un mensaje.
  4. Regresa a la pantalla principal (opcionalmente, cierra la pestaña o el navegador).
  5. Conéctate.
  6. El mensaje se envía en segundo plano.

Poder enviar en segundo plano de esta manera también genera una mejora percibida en el rendimiento. La app no necesita hacer tanta importancia con el envío de mensajes, por lo que puede agregarlo al resultado de inmediato.

Cómo solicitar una sincronización en segundo plano

En un verdadero estilo de Web extensible, esta es una función de bajo nivel que te brinda la libertad de hacer lo que necesitas. Solicitas que un evento se active cuando el usuario tiene conectividad, que es inmediato si el usuario ya la tiene. Luego, escuchas ese evento y haces lo que necesites.

Al igual que los mensajes push, utiliza un service worker como destino del evento, lo que le permite funcionar cuando la página no está abierta. Para comenzar, regístrate para una sincronización desde una página:

// Register your service worker:
navigator.serviceWorker.register('/sw.js');

// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
  return swRegistration.sync.register('myFirstSync');
});
 ```

Then listen for the event in `/sw.js`:

```js
self.addEventListener('sync', function(event) {
  if (event.tag == 'myFirstSync') {
    event.waitUntil(doSomeStuff());
  }
});

Eso es todo. En el ejemplo anterior, doSomeStuff() debe mostrar una promesa que indique el éxito o el fracaso de cualquier cosa que esté intentando hacer. Si se cumple, la sincronización está completa. Si falla, se programará otra sincronización para que se vuelva a intentar. Las sincronizaciones de reintento también esperan la conectividad y emplean una retirada exponencial.

El nombre de etiqueta de la sincronización ("myFirstSync" en el ejemplo anterior) debe ser único para una sincronización determinada. Si te registras para una sincronización con la misma etiqueta que una sincronización pendiente, se combina con la sincronización existente. Esto significa que puedes registrarte para una sincronización de “borrar la bandeja de salida” cada vez que el usuario envíe un mensaje. Sin embargo, si envía 5 mensajes sin conexión, solo recibirás una sincronización cuando se conecte a Internet. Si deseas tener cinco eventos de sincronización separados, simplemente utiliza etiquetas únicas.

Esta es una demostración sencilla que hace lo mínimo; utiliza el evento de sincronización para mostrar una notificación.

¿Para qué puedo usar la sincronización en segundo plano?

Idealmente, lo usarás para programar el envío de datos que te importen más allá del ciclo de vida de la página. Mensajes de chat, correos electrónicos, actualizaciones de documentos, cambios en la configuración, cargas de fotos... cualquier cosa que desees que llegue al servidor, incluso si el usuario sale de la pestaña o cierra la pestaña. La página podría almacenarlos en un almacén de "buzón de salida" en indexDB, y el service worker los recuperaría y enviaría.

Sin embargo, también puedes usarlo para recuperar pequeños fragmentos de datos...

Otra demostración.

Esta es la demostración de Wikipedia sin conexión que creé para Sobrecarga de la carga de la página. Desde entonces, le agregué la magia de sincronización en segundo plano.

Pruébalo. Asegúrate de usar Chrome 49 o una versión posterior y, luego, haz lo siguiente:

  1. Ve a cualquier artículo, como Chrome.
  2. Desconectarte (ya sea en modo de avión o unirte a un proveedor de telefonía celular terrible como yo)
  3. Haz clic en un vínculo a otro artículo.
  4. Se te informará que la página no se cargó (esto también aparecerá si la página solo demora un tiempo en cargarse).
  5. Acepta las notificaciones.
  6. Cierra el navegador.
  7. Conectarse
  8. Recibirás una notificación cuando el artículo se descargue, almacene en caché y esté listo para verlo.

Con este patrón, el usuario puede guardar su teléfono en el bolsillo y continuar con su vida, ya que sabe que el teléfono les alertará cuando se recupere cuando lo desee.

Permisos

Las demostraciones que te mostré usan notificaciones web, que requieren permiso, pero la sincronización en segundo plano no lo requiere.

A menudo, los eventos de sincronización se completan mientras el usuario tiene una página abierta en el sitio, por lo que solicitar su permiso sería una mala experiencia. En cambio, limitamos cuándo se pueden registrar y activar las sincronizaciones para evitar abusos. Por ejemplo:

  • Solo puedes registrarte para un evento de sincronización cuando el usuario tiene una ventana abierta con el sitio.
  • El tiempo de ejecución del evento está limitado, por lo que no puedes usarlos para hacer ping a un servidor cada x segundos, extraer bitcoins o lo que sea.

Por supuesto, estas restricciones pueden flexibilizarse o reforzarse en función del uso real.

Mejora progresiva

Pasará un tiempo hasta que todos los navegadores admitan la sincronización en segundo plano, especialmente porque Safari y Edge aún no son compatibles con los service workers. Pero la mejora progresiva es útil en este caso:

if ('serviceWorker' in navigator && 'SyncManager' in window) {
  navigator.serviceWorker.ready.then(function(reg) {
    return reg.sync.register('tag-name');
  }).catch(function() {
    // system was unable to register for a sync,
    // this could be an OS-level restriction
    postDataFromThePage();
  });
} else {
  // serviceworker/sync not supported
  postDataFromThePage();
}

Si los service workers o la sincronización en segundo plano no están disponibles, simplemente publica el contenido de la página como lo harías hoy.

Es útil usar la sincronización en segundo plano incluso si parece que el usuario tiene una buena conectividad, ya que te protege contra las navegaciones y el cierre de pestañas durante el envío de datos.

El futuro

Nuestro objetivo es ofrecer la sincronización en segundo plano a una versión estable de Chrome durante el primer semestre de 2016, mientras trabajamos en una variante, la "sincronización periódica en segundo plano". Con la sincronización periódica en segundo plano, puedes solicitar un evento restringido por el intervalo de tiempo, el estado de la batería y el estado de la red. Esto requiere permiso del usuario, por supuesto, y también depende del navegador para saber cuándo y con qué frecuencia se activan estos eventos. En otras palabras, un sitio de noticias podría solicitar la sincronización a cada hora, pero el navegador sabrá que solo lees ese sitio a las 07:00, por lo que la sincronización se activará diariamente a las 6:50. Esta idea es un poco más alejada de la sincronización única, pero llegará pronto.

Poco a poco, estamos incorporando patrones exitosos de iOS y Android a la Web, sin dejar de retener lo que hace que la Web sea genial.