Événements push

À ce stade, nous avons vu comment abonner un utilisateur et envoyer un message push. L'étape suivante consiste à recevoir ce message push sur l'appareil de l'utilisateur et à afficher une notification (et effectuer toute autre tâche que nous pourrions effectuer).

Événement push

Lorsqu'un message est reçu, un événement push est envoyé à votre service worker.

Le code permettant de configurer un écouteur d'événements push doit être assez semblable à tout autre écouteur d'événements que vous écririez 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 partie de ce code la plus étrange pour la plupart des développeurs qui débutent avec les service workers est la variable self. self est couramment utilisé dans Web Workers, à savoir un service worker. self fait référence au champ d'application global, un peu comme window dans une page Web. Toutefois, pour les workers Web et les service workers, self fait référence au worker lui-même.

Dans l'exemple ci-dessus, self.addEventListener() peut être considéré comme l'ajout d'un écouteur d'événements au service worker lui-même.

Dans l'exemple d'événement push, nous vérifions s'il y a des données et affichons quelque chose sur la console.

Il existe d'autres façons d'analyser les données d'un événement 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 plupart des utilisateurs utilisent json() ou text() en fonction de ce qu'ils attendent de leur application.

Cet exemple montre comment ajouter un écouteur d'événements push et comment accéder aux données, mais il lui manque deux fonctionnalités très importantes. Il n'affiche pas de notification et n'utilise pas event.waitUntil().

Attendre jusqu'à

L'une des choses à comprendre sur les service workers est que vous avez peu de contrôle sur le moment où le code du service worker est exécuté. Le navigateur décide quand l'activer et quand l'arrêter. La seule façon de pouvoir dire au navigateur "Hé, je suis très occupé à faire des choses importantes", est de transmettre une promesse à la méthode event.waitUntil(). Ainsi, le navigateur maintiendra le service worker en cours d'exécution jusqu'à ce que la promesse que vous avez transmise soit satisfaite.

Avec les événements push, vous devez également afficher une notification avant que la promesse que vous avez transmise ne soit perçue.

Voici un exemple de base d'affichage d'une notification:

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

    event.waitUntil(promiseChain);
});

Appeler self.registration.showNotification() est la méthode qui affiche une notification à l'utilisateur et renvoie une promesse qui se résout une fois la notification affichée.

Pour que cet exemple soit aussi clair que possible, nous avons attribué cette promesse à une variable appelée promiseChain. Il est ensuite transmis à event.waitUntil(). Je sais que c'est très détaillé, mais j'ai constaté qu'un certain nombre de problèmes ont abouti à une mauvaise compréhension de ce qui doit être transmis dans waitUntil() ou à la non-conformité des chaînes de promesses.

Voici un exemple plus compliqué avec une requête réseau pour les données et le suivi de l'événement push avec Analytics:

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);
});

Ici, nous appelons une fonction qui renvoie une promesse pushReceivedTracking() qui, pour les besoins de cet exemple, nous permet de faire semblant d'envoyer une requête réseau à notre fournisseur de solutions d'analyse. Nous effectuons également une requête réseau, obtenons la réponse et affichons une notification utilisant les données de réponse pour le titre et le message de la notification.

Nous pouvons nous assurer que le service worker reste actif pendant que ces deux tâches sont effectuées en combinant ces promesses avec Promise.all(). La promesse résultante est transmise à event.waitUntil(), ce qui signifie que le navigateur attend la fin des deux promesses avant de vérifier qu'une notification a été affichée et d'arrêter le service worker.

Nous devons nous soucier de waitUntil() et de son utilisation, car l'un des problèmes les plus courants rencontrés par les développeurs est que lorsque la chaîne de promesses est incorrecte ou non fonctionnelle, Chrome affiche la notification "par défaut" :

Image de la notification par défaut dans Chrome

Chrome n'affiche la notification "Ce site a été mis à jour en arrière-plan" que lorsqu'un message push est reçu et que l'événement push dans le service worker n'affiche pas de notification une fois la promesse transmise à event.waitUntil() terminée.

La principale raison pour laquelle les développeurs sont avertis est que leur code appelle souvent self.registration.showNotification(), mais qu'ils ne respectent pas la promesse renvoyée. La notification par défaut s'affiche par intermittence. Par exemple, si nous supprimons le retour pour self.registration.showNotification() dans l'exemple ci-dessus, nous risquons de voir cette notification.

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);
});

Comme vous pouvez le voir, il est facile de passer à côté.

N'oubliez pas : si cette notification s'affiche, vérifiez vos chaînes de promesses et event.waitUntil().

Dans la section suivante, nous verrons comment styliser les notifications et quel contenu nous pouvons afficher.

Étapes suivantes

Ateliers de programmation