Presentamos la sincronización en segundo plano

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

El problema

Internet es un excelente lugar para perder tiempo. Si no perdiéramos tiempo en Internet, no sabríamos que a los gatos no les gustan las flores, que a los camaleones les encantan las burbujas o que nuestro propio Eric Bidelman es un héroe del golf de mesa de finales de los 90.

Pero, a veces, no queremos perder el tiempo. La experiencia del usuario deseada es más como:

  1. Teléfono fuera del bolsillo.
  2. Lograr un objetivo menor
  3. El teléfono vuelve al bolsillo.
  4. Reanuda tu vida.

Lamentablemente, esta experiencia suele verse afectada por una conectividad deficiente. A todos nos ha pasado. Estás mirando una pantalla blanca o un ícono giratorio, y sabes que deberías rendirte y seguir con tu vida, pero le das otros 10 segundos por si acaso. ¿Después de esos 10 segundos? Nada.

Pero ¿por qué rendirte ahora? Ya invertiste tiempo, así que sería un desperdicio no obtener nada, por lo que sigues esperando. En este punto, deseas renunciar, pero sabes que el segundo en que lo haces es el segundo antes de que todo se haya cargado si solo hubieras esperado.

Los servicios en primer plano resuelven la parte de carga de la página, ya que te permiten entregar contenido desde una caché. Pero ¿qué sucede cuando la página necesita enviar algo al servidor?

En este momento, si el usuario presiona "Enviar" en un mensaje, debe mirar una lista de opciones hasta que se complete. Si intenta salir de la página o cerrar la pestaña, usamos onbeforeunload para mostrar un mensaje como "No, necesito que mires este ícono giratorio un poco más. Lo siento". Si el usuario no tiene conexión, le decimos: "Lo siento, debes volver más tarde y volver a intentarlo".

Esto es basura. La sincronización en segundo plano te permite hacer más.

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, y sincronización en segundo plano.

Si el usuario intenta enviar un mensaje cuando no tiene conectividad, el mensaje se envía en segundo plano una vez que se establece la conectividad.

Desde marzo de 2016, la sincronización en segundo plano está disponible en Chrome a partir de la versión 49. Sigue estos pasos para ver cómo funciona:

  1. Abre Emojoy.
  2. Desconecta el dispositivo (ya sea con el modo de avión o visita tu jaula de Faraday local).
  3. Escribe un mensaje.
  4. Regresa a la pantalla principal (si lo deseas, 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 del rendimiento. La app no necesita hacer un gran esfuerzo para enviar el mensaje, por lo que puede agregarlo al resultado de inmediato.

Cómo solicitar una sincronización en segundo plano

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

Al igual que la mensajería push, utiliza un service worker como destino del evento, lo que le permite funcionar cuando la página no está abierta. En primer lugar, regístrate para realizar 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 lo anterior, doSomeStuff() debe mostrar una promesa que indique el éxito o el error de lo que intenta hacer. Si se cumple, la sincronización se completa. Si falla, se programará otra sincronización para reintentarlo. Los reintentos de sincronización también esperan la conectividad y emplean una retirada exponencial.

El nombre de la 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, esta se fusiona con la sincronización existente. Esto significa que puedes registrarte para una sincronización de "borrado de carpeta Recibidos" cada vez que el usuario envíe un mensaje, pero si envía 5 mensajes sin conexión, solo recibirás una sincronización cuando esté en línea. Si deseas 5 eventos de sincronización independientes, usa etiquetas únicas.

Esta es una demostración simple que hace lo mínimo: usa el evento de sincronización para mostrar una notificación.

¿Para qué podría usar la sincronización en segundo plano?

Lo ideal es que lo uses para programar el envío de datos que te interesen más allá de la vida útil de la página. Mensajes de chat, correos electrónicos, actualizaciones de documentos, cambios de configuración, cargas de fotos… todo lo que quieras enviar al servidor, incluso si el usuario sale de la página o cierra la pestaña. La página podría almacenarlos en un almacén de "bandeja de salida" en IndexedDB, 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 Acelerar la carga de la página. Desde entonces, le agregué un poco de magia de la sincronización en segundo plano.

Pruébalo por tu cuenta. Asegúrate de usar Chrome 49 o versiones posteriores y, luego, haz lo siguiente:

  1. Abre cualquier artículo (por ejemplo, Chrome).
  2. Desconecta el dispositivo (ya sea con el modo de avión o conectándote a un proveedor de servicios móviles terrible como yo).
  3. Haz clic en un vínculo a otro artículo.
  4. Se te informará que no se pudo cargar la página (también aparecerá si la página tarda un poco en cargarse).
  5. Aceptar las notificaciones
  6. Cierra el navegador.
  7. Conectarse
  8. Recibirás una notificación cuando el artículo se descargue, se almacenen en caché y esté listo para ver.

Con este patrón, el usuario puede guardar el teléfono en el bolsillo y seguir con su vida, sabiendo que el teléfono le alertará cuando recupere lo que buscaba.

Permisos

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

Los eventos de sincronización suelen completarse mientras el usuario tiene una página abierta en el sitio, por lo que solicitar su permiso sería una experiencia negativa. En su lugar, limitaremos 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 en 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, minar bitcoins ni hacer lo que sea.

Por supuesto, estas restricciones pueden relajarse o endurecerse según el uso real.

Mejora progresiva

Pasará un tiempo hasta que todos los navegadores admitan la sincronización en segundo plano, en especial porque Safari y Edge aún no admiten los service workers. Pero la mejora progresiva ayuda 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, publica el contenido de la página como lo harías hoy.

Vale la pena usar la sincronización en segundo plano, incluso si el usuario parece tener una buena conectividad, ya que te protege contra las navegaciones y los cierres de pestañas durante el envío de datos.

El futuro

Nuestro objetivo es lanzar la sincronización en segundo plano en una versión estable de Chrome en 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 intervalo de tiempo, estado de la batería y estado de la red. Por supuesto, esto requeriría el permiso del usuario, y también dependerá del navegador cuándo y con qué frecuencia se activen estos eventos. En otras palabras, un sitio de noticias podría solicitar una sincronización cada hora, pero el navegador podría saber que solo leíste ese sitio a las 7:00 a.m., por lo que la sincronización se activaría diariamente a las 6:50 a.m. Esta idea está un poco más alejada que la sincronización única, pero pronto lo haremos.

Poco a poco, llevamos patrones exitosos de Android y iOS a la Web, sin dejar de lado lo que la hace genial.