Eventi push

Matt Gaunt

A questo punto, abbiamo visto come iscrivere un utente e inviare un messaggio push. Il passaggio successivo consiste nel ricevere questo messaggio push sul dispositivo dell'utente e visualizzare una notifica (oltre a eseguire qualsiasi altra operazione che potremmo voler fare).

L'evento push

Quando viene ricevuto un messaggio, viene inviato un evento push nel service worker.

Il codice per configurare un listener di eventi push dovrebbe essere molto simile a qualsiasi altro listener di eventi che scriveresti 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 per la maggior parte degli sviluppatori che non hanno familiarità con i service worker è la variabile self. self viene comunemente utilizzato nei web worker, come i 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 di evento push, controlliamo se sono presenti dati e stampiamo un messaggio nella 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 delle persone utilizza json() o text() a seconda di ciò che si aspetta dalla propria 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 utilizza event.waitUntil().

Attendi fino a

Uno degli aspetti da comprendere sui service worker è che hai poco controllo su quando 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 promise al metodo event.waitUntil(). In questo modo, il browser manterrà il service worker in esecuzione fino a quando la promise che hai passato non sarà stata risolta.

Con gli eventi push, esiste un requisito aggiuntivo: devi mostrare una notifica prima che la promise che hai passato venga risolta.

Ecco un esempio di 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 una volta visualizzata la notifica.

Per mantenere questo esempio il più chiaro possibile, ho assegnato questa promise a una variabile denominata promiseChain. Questo viene poi passato a event.waitUntil(). So che è molto dettagliato, ma ho visto una serie di problemi che sono culminati a causa di un'errata comprensione di ciò che dovrebbe essere passato a waitUntil() o di catene di promise interrotte.

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

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 promise pushReceivedTracking(), che, per il bene dell'esempio, possiamo fingere che effettuerà una richiesta di rete al nostro fornitore di analisi. Inoltre, effettuiamo una richiesta di rete, riceviamo la risposta e mostriamo una notifica utilizzando i dati della risposta per il titolo e il messaggio della notifica.

Possiamo assicurarci che il service worker rimanga attivo durante l'esecuzione di entrambe le attività combinando queste promise con Promise.all(). La promise risultante viene passata a event.waitUntil(), il che significa che il browser attenderà il completamento di entrambe le promise prima di verificare che sia stata visualizzata una notifica e terminare il service worker.

Il motivo per cui dovremmo preoccuparci di waitUntil() e di come utilizzarlo è che uno dei problemi più comuni che gli sviluppatori devono affrontare è che, quando la catena di promise è errata o interrotta, Chrome mostra questa notifica "predefinita":

Un'immagine della notifica predefinita in Chrome

Chrome mostrerà la notifica "Questo sito è stato aggiornato in background" solo quando viene ricevuto un messaggio push e l'evento push nel service worker non mostra una notifica dopo il completamento della promise passata a event.waitUntil().

Il motivo principale per cui gli sviluppatori vengono colti di sorpresa è che il loro codice spesso chiama self.registration.showNotification(), ma non fa nulla con la promise restituita. Ciò comporta la visualizzazione intermittente della notifica predefinita. Ad esempio, potremmo rimuovere il ritorno per self.registration.showNotification() nell'esempio precedente e rischiare 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);
});

Come vedi, è facile non accorgersene.

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

Nella prossima sezione, vedremo cosa possiamo fare per applicare uno stile alle notifiche e quali contenuti possiamo mostrare.

Passaggi successivi

Codelab