Eventos push

En este punto, abarcamos la suscripción de un usuario y el envío de un mensaje push. El siguiente paso es recibir este mensaje push en el dispositivo del usuario y mostrar una notificación (además de realizar cualquier otra tarea que queramos realizar).

El evento push

Cuando se recibe un mensaje, se envía un evento push en tu service worker.

El código para configurar un objeto de escucha de eventos push debe ser bastante similar al de cualquier otro objeto de escucha de eventos que escribirías en JavaScript:

self.addEventListener('push', function(event) {
    if (event.data) {
    console.log('This push event has data: ', event.data.text());
    } else {
    console.log('This push event has no data.');
    }
});

La variable self es la parte más extraña de este código para la mayoría de los desarrolladores que recién comienzan a trabajar con los service workers. self es de uso general en Web Workers, que es un service worker. self se refiere al alcance global, como window en una página web. Sin embargo, en el caso de los trabajadores web y los service worker, self se refiere al trabajador en sí.

En el ejemplo anterior, se puede considerar que self.addEventListener() agrega un objeto de escucha de eventos al service worker.

Dentro del ejemplo del evento push, verificamos si hay datos y, luego, imprimimos algo en la consola.

Existen otras formas de analizar datos de un evento push:

// Returns string
event.data.text()

// Parses data as JSON string and returns an Object
event.data.json()

// Returns blob of data
event.data.blob()

// Returns an arrayBuffer
event.data.arrayBuffer()

La mayoría de las personas usan json() o text(), según lo que esperan de su aplicación.

En este ejemplo, se muestra cómo agregar un objeto de escucha de eventos push y cómo acceder a los datos, pero faltan dos elementos de funcionalidad muy importantes. No muestra una notificación y no usa event.waitUntil().

Esperar hasta

Uno de los aspectos que debes comprender sobre los service worker es que tienes poco control sobre el momento en que se ejecutará el código del service worker. El navegador decide cuándo activarlo y cuándo finalizarlo. La única forma de indicarle al navegador que estoy muy ocupado haciendo cosas importantes es pasar una promesa al método event.waitUntil(). De esta manera, el navegador mantendrá el service worker en ejecución hasta que se cumpla la promesa que pasaste.

Con los eventos push, existe un requisito adicional que establece que debes mostrar una notificación antes de que se establezca la promesa que pasaste.

A continuación, se incluye un ejemplo básico de una notificación:

self.addEventListener('push', function(event) {
    const promiseChain = self.registration.showNotification('Hello, World.');

    event.waitUntil(promiseChain);
});

Llamar a self.registration.showNotification() es el método que muestra una notificación al usuario y muestra una promesa que se resolverá una vez que se muestre la notificación.

Para mantener este ejemplo lo más claro posible, asigné esta promesa a una variable llamada promiseChain. Luego, se pasa a event.waitUntil(). Sé que esto es muy detallado, pero vi varios problemas que culminaron como resultado de malentendidos de lo que se debía pasar a waitUntil() o como resultado de cadenas de promesa rotas.

Un ejemplo más complicado con una solicitud de red de datos y seguimiento del evento push con estadísticas podría verse así:

self.addEventListener('push', function(event) {
    const analyticsPromise = pushReceivedTracking();
    const pushInfoPromise = fetch('/api/get-more-data')
    .then(function(response) {
        return response.json();
    })
    .then(function(response) {
        const title = response.data.userName + ' says...';
        const message = response.data.message;

        return self.registration.showNotification(title, {
        body: message
        });
    });

    const promiseChain = Promise.all([
    analyticsPromise,
    pushInfoPromise
    ]);

    event.waitUntil(promiseChain);
});

Aquí llamamos a una función que muestra una promesa pushReceivedTracking(), la cual, a los fines de este ejemplo, podemos simular que realizará una solicitud de red a nuestro proveedor de estadísticas. También realizaremos una solicitud de red, obtendremos la respuesta y mostraremos una notificación con los datos de las respuestas para el título y el mensaje de la notificación.

Combinamos estas promesas con Promise.all() para asegurarnos de que el service worker se mantenga activo mientras se realizan ambas tareas. La promesa resultante se pasa a event.waitUntil(), lo que significa que el navegador esperará hasta que ambas promesas hayan finalizado antes de verificar que se haya mostrado una notificación y finalizar el service worker.

El motivo por el que debemos preocuparnos por waitUntil() y cómo usarlo es que uno de los problemas más comunes que enfrentan los desarrolladores es que, cuando la cadena de promesas es incorrecta o no funciona, Chrome mostrará esta notificación “predeterminada”:

Una imagen de la notificación predeterminada en Chrome

Chrome solo mostrará la notificación "Este sitio se actualizó en segundo plano" cuando se reciba un mensaje push y el evento push en el service worker no muestre una notificación después de que finalice la promesa que se pasó a event.waitUntil().

El motivo principal por el que los desarrolladores quedan atrapados por esta situación es que, a menudo, su código llamará a self.registration.showNotification(), pero no harán nada con la promesa que muestra. Esto hace que se muestre la notificación predeterminada de forma intermitente. Por ejemplo, podríamos quitar el resultado de self.registration.showNotification() en el ejemplo anterior y corremos el riesgo de ver esta notificación.

self.addEventListener('push', function(event) {
    const analyticsPromise = pushReceivedTracking();
    const pushInfoPromise = fetch('/api/get-more-data')
    .then(function(response) {
        return response.json();
    })
    .then(function(response) {
        const title = response.data.userName + ' says...';
        const message = response.data.message;

        self.registration.showNotification(title, {
        body: message
        });
    });

    const promiseChain = Promise.all([
    analyticsPromise,
    pushInfoPromise
    ]);

    event.waitUntil(promiseChain);
});

Puedes ver que es algo fácil pasar por alto.

Recuerda que, si ves esa notificación, revisa las cadenas de promesa y event.waitUntil().

En la siguiente sección, veremos qué podemos hacer para diseñar notificaciones y qué contenido podemos mostrar.

Próximos pasos

Code labs