Eventi push

Matt Gaunt

A questo punto, abbiamo parlato dell'iscrizione di un utente e dell'invio di un messaggio push. Il passaggio successivo prevede la ricezione di questo messaggio push sul dispositivo dell'utente e la visualizzazione di una notifica (oltre a eseguire qualsiasi altra operazione eventualmente necessaria).

L'evento push

Alla ricezione di un messaggio, viene inviato un evento push al service worker.

Il codice per configurare un listener di eventi push dovrebbe essere molto simile a qualsiasi altro listener di eventi da scrivere in 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 parte più strana di questo codice alla maggior parte degli sviluppatori che non conoscono i service worker è la variabile self. self viene comunemente utilizzato nei web worker, ossia un service worker. self si riferisce all'ambito globale, un po' come window in una pagina web. Tuttavia, per i web worker e i service worker, self si riferisce al worker stesso.

Nell'esempio precedente, self.addEventListener() può essere considerato come l'aggiunta di un listener di eventi al service worker stesso.

Nell'esempio dell'evento push, controlliamo la presenza di dati e stampiamo qualcosa sulla console.

Esistono altri modi per analizzare i dati di 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 maggior parte degli utenti utilizza json() o text() in base a ciò che si aspetta dall'applicazione.

Questo esempio mostra come aggiungere un listener di eventi push e come accedere ai dati, ma mancano due funzionalità molto importanti. Non mostra una notifica e non sta utilizzando event.waitUntil().

Attendi fino a

Uno degli aspetti dei Service worker da comprendere è che hai un controllo minimo sul momento in cui verrà eseguito il codice del service worker. Il browser decide quando attivarlo e quando terminarlo. L'unico modo per dire al browser "Ehi, sono molto impegnato a fare cose importanti" è passare una promessa al metodo event.waitUntil(). In questo modo il browser manterrà in esecuzione il service worker fino a quando la promessa che hai lasciato non si sarà saldata.

Per gli eventi push, esiste un ulteriore requisito che prevede la visualizzazione di una notifica prima che la promessa che hai trasmesso si sia stabilizzata.

Ecco un esempio base di visualizzazione di una notifica:

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

    event.waitUntil(promiseChain);
});

La chiamata a self.registration.showNotification() è il metodo che mostra una notifica all'utente e restituisce una promessa che verrà risolta non appena la notifica verrà visualizzata.

Per garantire la massima chiarezza dell'esempio, ho assegnato questa promessa a una variabile chiamata promiseChain. Questo valore viene quindi trasmesso a event.waitUntil(). So che queste informazioni sono molto dettagliate, ma ho riscontrato una serie di problemi che sono culminati a causa di un malinteso su cosa trasmettere in waitUntil() o come conseguenza di una catena di promesse non funzionante.

Un esempio più complicato con una richiesta di rete per i dati e il monitoraggio dell'evento push con analisi potrebbe avere il seguente aspetto:

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

Qui chiamiamo una funzione che restituisce una promessa pushReceivedTracking() che, a fini di esempio, possiamo simulare che farà una richiesta di rete al nostro provider di analisi. Stiamo anche effettuando una richiesta di rete, ricevendo la risposta e mostrando una notifica utilizzando i dati delle risposte per il titolo e il messaggio della notifica.

Possiamo assicurare che il service worker resti attivo mentre entrambe queste attività vengono completate combinando queste promesse con Promise.all(). La promessa risultante viene trasmessa a event.waitUntil(), ossia il browser attenderà il completamento di entrambe le promesse prima di verificare che sia stata visualizzata una notifica e di terminare il service worker.

Il motivo per cui dovremmo preoccuparci di waitUntil() e di come utilizzarlo è che uno dei problemi più comuni riscontrati dagli sviluppatori è che, quando la catena di promesse non è corretta o non funziona, Chrome mostrerà questa notifica "predefinita":

Un'immagine della notifica predefinita in Chrome

Chrome mostra la notifica "Questo sito è stato aggiornato in background" soltanto quando viene ricevuto un messaggio push e l'evento push nel service worker non mostra alcuna notifica dopo il termine della promessa passata a event.waitUntil().

Il motivo principale per cui gli sviluppatori vengono colti da questa situazione è che il loro codice spesso chiama self.registration.showNotification(), ma non fanno nulla con la promessa che restituisce. A intermittenza, viene visualizzata la notifica predefinita. Ad esempio, potremmo rimuovere il valore restituito per self.registration.showNotification() nell'esempio precedente e corriamo il rischio di visualizzare questa notifica.

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

Puoi vedere quanto è facile farsi sfuggire questa opportunità.

Ricorda: se vedi questa notifica, controlla le tue catene di promesse e event.waitUntil().

Nella sezione successiva, vedremo cosa possiamo fare per definire lo stile delle notifiche e quali contenuti visualizzare.

Passaggi successivi

Codelab