Cómo usar un Service Worker para administrar notificaciones

Kate Jeffreys
Kate Jeffreys

En este codelab, usarás un service worker para administrar las notificaciones. En estas instrucciones, se presupone que ya conoces service workers y conceptos básicos para solicitar permisos de notificaciones y enviar notificaciones. Si necesitas repasar las notificaciones, consulta la Comienza a usar la API de Notifications en este codelab. Para obtener más información sobre los service workers, consulta la Introducción a los service workers de Matt Gaunt.

Las notificaciones se bloquean automáticamente en la app incorporada de Glitch, por lo que no podrás obtener una vista previa de la app en esta página. En cambio, esto es lo que debes hacer:

  1. Haz clic en Remix para editar para que el proyecto se pueda editar.
  2. Para obtener una vista previa del sitio, presiona Ver app. Luego, presiona Pantalla completa pantalla completa

El problema se debería abrir en una nueva pestaña de Chrome.

A medida que trabajes en este codelab, realiza cambios en el código de la Glitch incorporada en esta página. Actualiza la pestaña nueva con la app publicada para ver los cambios.

Familiarízate con la app de ejemplo y el código de inicio

Para comenzar, observa la app activa en la nueva pestaña de Chrome:

  1. Presiona `Control + Mayúsculas + J` (o `Command + Option + J` en Mac) para abrir Herramientas para desarrolladores.
  2. Haz clic en la pestaña Consola.

  3. Asegúrate de que la opción Información esté seleccionada en el menú desplegable Niveles. junto al cuadro Filtro.

  4. En la consola de Herramientas para desarrolladores de tu app activa, deberías ver un mensaje de consola:

    TODO: Implement getRegistration().

    Este es un mensaje de un stub de función que implementarás en este codelab.

Ahora, echemos un vistazo al código de la app de ejemplo en el Glitch incorporado en esta página.

  1. En la falla incorporada, observa public/index.js:

    • Hay cuatro stubs para las funciones que implementarás: registerServiceWorker, getRegistration, unRegisterServiceWorker y sendNotification.

    • La función requestPermission solicita el permiso del usuario para enviar notificaciones. Si realizaste el codelab Cómo comenzar a usar la API de Notifications, notarás que aquí se usa su función requestPermission. La única diferencia es que ahora también actualiza la interfaz de usuario después de resolver la solicitud de permiso.

    • La función updateUI actualiza todos los botones y mensajes de la app.

    • La función initializePage detecta funciones para la capacidad del service worker en el navegador y actualiza la interfaz de usuario de la app.

    • La secuencia de comandos espera hasta que la página se cargue y la inicializa.

  2. En el Glitch incorporado, abre public/service-worker.js.

    Tal como lo sugiere el nombre, agregarás código a la app para registrar este archivo como service worker.

    Aunque la app aún no usa el archivo, este contiene código de inicio que imprimirá un mensaje en la consola cuando se active el service worker.

    Agregarás código a public/service-worker.js para controlar las notificaciones cuando el service worker las reciba.

Registra el service worker

En este paso, escribirás código que se ejecute Cuando el usuario hace clic en Registrar service worker en la IU de la app Este código registrará public/service-worker.js como service worker.

  1. En el editor de Glitch incorporado, abre public/index.js. Reemplaza la función registerServiceWorker por el siguiente código:

    // Use the Service Worker API to register a service worker.
    async function registerServiceWorker() {
      await navigator.serviceWorker.register('./service-worker.js')
      updateUI();
    }
    

    Ten en cuenta que registerServiceWorker usa la declaración async function para que el manejo de promesas sea más conveniente. Esto te permite await el valor resuelto de una Promise. Por ejemplo, la función anterior espera el resultado del registro de un service worker antes de actualizar la IU. Consulta await en MDN para obtener más información.

  2. Ahora que el usuario puede registrar un service worker, puedes obtener una referencia al objeto de registro del service worker. En public/index.js, reemplaza la función getRegistration por el siguiente código:

    // Get the current service worker registration.
    function getRegistration() {
      return navigator.serviceWorker.getRegistration();
    }
    

    La función anterior usa API de Service Worker para obtener el registro del service worker actual, si existe. Por lo tanto, obtener una referencia al registro del service worker es un poco más conveniente.

  • Para completar la funcionalidad de registro del service worker, agrega código para cancelar el registro del service worker. Reemplaza la función unRegisterServiceWorker por el siguiente código:

    // Unregister a service worker, then update the UI.
    async function unRegisterServiceWorker() {
      // Get a reference to the service worker registration.
      let registration = await getRegistration();
      // Await the outcome of the unregistration attempt
      // so that the UI update is not superceded by a
      // returning Promise.
      await registration.unregister();
      updateUI();
    }
    

En la pestaña donde estás viendo la app en vivo, vuelve a cargar la página. Los botones Register service worker y Unregister service worker ahora deberían funcionar.

Envía notificaciones al service worker

En este paso, escribirás código que se ejecutará cuando el usuario haga clic en Enviar una notificación en la IU de la app. Este código creará una notificación, verificará que un service worker esté registrado y, luego, enviará la notificación al service worker con su método postMessage.

En el editor de Glitch incorporado, abre public/index.js y Reemplaza la función sendNotification por el siguiente código:

// Create and send a test notification to the service worker.
async function sendNotification() {
  // Use a random number as part of the notification data
  // (so you can tell the notifications apart during testing!)
  let randy = Math.floor(Math.random() * 100);
  let notification = {
    title: 'Test ' + randy,
    options: { body: 'Test body ' + randy }
  };
  // Get a reference to the service worker registration.
  let registration = await getRegistration();
  // Check that the service worker registration exists.
  if (registration) {
    // Check that a service worker controller exists before
    // trying to access the postMessage method.
    if (navigator.serviceWorker.controller) {
      navigator.serviceWorker.controller.postMessage(notification);
    } else {
      console.log('No service worker controller found. Try a soft reload.');
    }
  }
}

Esto es lo que hace el código:

  • sendNotification es una función asíncrona, por lo que puedes usar await para obtener una referencia al registro del service worker.

  • El método postMessage del service worker envía datos de la app al service worker. Consulta la documentación de MDN sobre postMessage para obtener más información.

  • El código verifica la presencia de la propiedad navigator.serviceWorker.controller antes de intentar acceder a la función postMessage. navigator.serviceWorker.controller será null si no hay un service worker activo o si se realizó la actualización forzada de la página (Shift+Volver a cargar). Consulta la documentación del controlador de ServiceWorker en MDN para obtener más información.

Cómo controlar las notificaciones en el service worker

En este paso, escribirás código en el service worker que controlará los mensajes publicados en él y mostrará notificaciones al usuario.

En el editor de Glitch incorporado, abre public/service-worker.js. Agrega el siguiente código al final del archivo:

// Show notification when received
self.addEventListener('message', (event) => {
  let notification = event.data;
  self.registration.showNotification(
    notification.title,
    notification.options
  ).catch((error) => {
    console.log(error);
  });
});

Aquí le presentamos una breve explicación:

  • self es una referencia al service worker en sí.

  • Si bien el service worker ahora controla la visualización de notificaciones, la IU principal de la app sigue siendo responsable de obtener el permiso de notificaciones del usuario. Si no se otorga el permiso, se rechaza la promesa que muestra showNotification. En el código anterior, se usa un bloque catch para evitar un error de rechazo Promise no detectado y manejar este error con un poco más de facilidad.

Si no puedes avanzar, consulta glitch.com/edit/#!/codelab-notifications-service-worker-completed para obtener el código completado.

Continúa con el siguiente codelab de esta serie: Cómo compilar un servidor de notificaciones push.