Push-Ereignisse

Matt Gaunt

Bisher haben wir das Abonnieren eines Nutzers und das Senden einer Push-Nachricht behandelt. Im nächsten Schritt wird diese Push-Nachricht auf dem Gerät des Nutzers empfangen und eine Benachrichtigung angezeigt. Außerdem können wir andere Aktionen ausführen.

Wenn eine Nachricht empfangen wird, wird in Ihrem Service Worker ein Push-Ereignis gesendet.

Der Code zum Einrichten eines Push-Ereignis-Listeners sollte ziemlich ähnlich wie jeder andere Ereignis-Listener sein, den Sie in JavaScript schreiben würden:

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

Für die meisten Entwickler, die noch keine Erfahrung mit Service Workern haben, ist die Variable self das Seltsamste an diesem Code. self wird häufig in Web Workers verwendet, zu denen auch Service Workers gehören. self bezieht sich auf den globalen Gültigkeitsbereich, ähnlich wie window auf einer Webseite. Bei Web Workern und Service Workern bezieht sich self jedoch auf den Worker selbst.

Im obigen Beispiel kann self.addEventListener() als Event-Listener für den Service Worker selbst angesehen werden.

Im Beispiel für Push-Ereignisse prüfen wir, ob Daten vorhanden sind, und drucken etwas in die Konsole.

Es gibt noch weitere Möglichkeiten, Daten aus einem Push-Ereignis zu parsen:

// 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()

Die meisten Nutzer verwenden json() oder text(), je nachdem, was sie von ihrer Anwendung erwarten.

In diesem Beispiel wird gezeigt, wie Sie einen Push-Ereignis-Listener hinzufügen und auf Daten zugreifen. Es fehlen jedoch zwei sehr wichtige Funktionen. Es wird keine Benachrichtigung angezeigt und event.waitUntil() wird nicht verwendet.

Warten bis

Bei Dienstarbeitern haben Sie nur wenig Kontrolle darüber, wann der Dienstarbeitercode ausgeführt wird. Der Browser entscheidet, wann er gestartet und wann er beendet wird. Die einzige Möglichkeit, dem Browser mitzuteilen, dass Sie gerade wichtige Dinge zu tun haben, besteht darin, ein Versprechen an die event.waitUntil()-Methode zu übergeben. Dadurch hält der Browser den Service Worker so lange am Laufen, bis das übergebene Versprechen erfüllt ist.

Bei Push-Ereignissen gilt außerdem die zusätzliche Anforderung, dass Sie eine Benachrichtigung anzeigen müssen, bevor das übergebene Versprechen erfüllt wurde.

Hier ein einfaches Beispiel für die Anzeige einer Benachrichtigung:

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

    event
.waitUntil(promiseChain);
});

Durch Aufrufen von self.registration.showNotification() wird dem Nutzer eine Benachrichtigung angezeigt. Es wird ein Promise zurückgegeben, das aufgelöst wird, sobald die Benachrichtigung angezeigt wurde.

Damit dieses Beispiel möglichst verständlich ist, habe ich dieses Versprechen einer Variablen namens promiseChain zugewiesen. Dieser wird dann an event.waitUntil() übergeben. Ich weiß, dass das sehr ausführlich ist, aber ich habe schon einige Probleme gesehen, die auf ein Missverständnis darüber zurückzuführen waren, was an waitUntil() übergeben werden sollte, oder auf gebrochene Versprechensketten.

Ein komplexeres Beispiel mit einer Netzwerkanfrage für Daten und dem Tracking des Push-Ereignisses mit Analytics könnte so aussehen:

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

Hier rufen wir eine Funktion auf, die ein Versprechen pushReceivedTracking() zurückgibt, das im Beispiel eine Netzwerkanfrage an unseren Analyseanbieter stellt. Außerdem stellen wir eine Netzwerkanfrage, rufen die Antwort ab und zeigen eine Benachrichtigung mit den Antwortdaten für den Titel und die Nachricht der Benachrichtigung an.

Wir können dafür sorgen, dass der Dienst-Worker aktiv bleibt, während beide Aufgaben ausgeführt werden, indem wir diese Versprechen mit Promise.all() kombinieren. Das resultierende Versprechen wird an event.waitUntil() übergeben. Das bedeutet, dass der Browser wartet, bis beide Versprechen abgeschlossen sind, bevor er prüft, ob eine Benachrichtigung angezeigt wurde, und den Dienst-Worker beendet.

Wir sollten uns mit waitUntil() und seiner Verwendung befassen, da eines der häufigsten Probleme, mit denen Entwickler konfrontiert sind, darin besteht, dass Chrome diese Standardbenachrichtigung anzeigt, wenn die Promise-Kette falsch oder unterbrochen ist:

Ein Bild der Standardbenachrichtigung in Chrome

Chrome zeigt die Benachrichtigung „Diese Website wurde im Hintergrund aktualisiert“ nur dann an, wenn eine Push-Nachricht empfangen wird und das Push-Ereignis im Service Worker keine Benachrichtigung anzeigt, nachdem das an event.waitUntil() übergebene Versprechen abgeschlossen ist.

Der Hauptgrund dafür, dass Entwickler in diese Falle tappen, ist, dass sie in ihrem Code oft self.registration.showNotification() aufrufen, aber nichts mit der zurückgegebenen Zusicherung tun. Dadurch wird die Standardbenachrichtigung gelegentlich angezeigt. Wenn wir beispielsweise die Rückgabe für self.registration.showNotification() im obigen Beispiel entfernen, besteht die Gefahr, dass diese Benachrichtigung angezeigt wird.

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

Sie können sich vorstellen, wie leicht das übersehen werden kann.

Wenn Sie diese Benachrichtigung sehen, prüfen Sie Ihre Versprechensketten und event.waitUntil().

Im nächsten Abschnitt sehen wir uns an, wie wir Benachrichtigungen gestalten und welche Inhalte wir anzeigen können.

Weitere Informationen

Code labs