Zdarzenia push

Do tej pory omawialiśmy subskrypcję użytkownika i wysyłanie powiadomienia push. Następnym krokiem jest odebranie wiadomości push na urządzeniu użytkownika i wyświetlenie powiadomienia (oraz wykonanie innych czynności).

Po otrzymaniu wiadomości w Twoim serwisie zostanie wysłane zdarzenie push.

Kod konfigurujący detektor zdarzenia push powinien być podobny do każdego innego detektora zdarzeń napisanego w 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.');
   
}
});

Najdziwniejszym elementem tego kodu dla większości deweloperów, którzy dopiero zaczynają korzystać z usług działających w tle, jest zmienna self. self jest często używany w skryptach Web Worker, które są usługami. self odnosi się do zakresu globalnego, podobnie jak window w przypadku strony internetowej. W przypadku skryptów web worker i service worker element self odnosi się do samego skryptu.

W przykładzie powyżej element self.addEventListener() można traktować jako dodanie odbiornika zdarzeń do samego serwisu.

W przykładzie zdarzenia push sprawdzamy, czy są jakieś dane, i wyświetlamy coś w konsoli.

Dane z zdarzenia push możesz też analizować na inne sposoby:

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

Większość osób używa json() lub text() w zależności od tego, czego oczekuje od aplikacji.

Ten przykład pokazuje, jak dodać odbiornik powiadomień push i jak uzyskać dostęp do danych, ale brakuje w nim 2 bardzo ważnych funkcji. Nie wyświetla powiadomienia i nie korzysta z elementu event.waitUntil().

Zaczekaj do

Jedną z rzeczy, które należy zrozumieć w przypadku skryptów service worker, jest to, że masz niewielką kontrolę nad tym, kiedy będzie uruchamiany kod skryptu. Przeglądarka decyduje, kiedy ją aktywować i kiedy zakończyć. Jedynym sposobem na poinformowanie przeglądarki „Czuję się bardzo zajęty, robię ważne rzeczy” jest przekazanie obietnicy do metody event.waitUntil(). W tym przypadku przeglądarka będzie utrzymywać usługę w stanie działania, dopóki przekazana obietnica nie zostanie spełniona.

W przypadku zdarzeń push obowiązuje dodatkowy wymóg wyświetlania powiadomienia przed spełnieniem obietnicy.

Oto podstawowy przykład wyświetlania powiadomienia:

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

    event
.waitUntil(promiseChain);
});

Wywołanie self.registration.showNotification() to metoda, która wyświetla powiadomienie użytkownikowi i zwraca obietnicę, która zostanie spełniona po wyświetleniu powiadomienia.

Aby przykład był jak najbardziej przejrzysty, przypisałem to obietnice do zmiennej o nazwie promiseChain. Następnie jest przekazywany do event.waitUntil(). Wiem, że to jest bardzo obszerne, ale widzieliśmy już wiele problemów, które wynikały z nieporozumień dotyczących tego, co powinno być przekazane do funkcji waitUntil(), lub z niespełnionych obietnic.

Bardziej skomplikowany przykład z żądaniem sieci o dane i śledzeniem zdarzenia push za pomocą Analytics może wyglądać tak:

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

W tym przykładzie wywołujemy funkcję, która zwraca obietnicę pushReceivedTracking(). Dla celów przykładu możemy założyć, że żądanie sieci zostanie wysłane do naszego dostawcy usług analitycznych. Wysyłamy też żądanie do sieci, aby uzyskać odpowiedź, a następnie wyświetlamy powiadomienie z danymi z odpowiedzi na potrzeby tytułu i tekstu powiadomienia.

Możemy zapewnić, aby usługa workera była aktywna podczas wykonywania obu tych zadań, łącząc te obietnice z Promise.all(). Wynik obietnicy jest przekazywany do event.waitUntil(), co oznacza, że przeglądarka będzie czekać, aż obie obietnice się zakończą, zanim sprawdzi, czy powiadomienie zostało wyświetlone, i zakończy działanie usługi.

Powinniśmy się martwić o to, jak używać waitUntil(), ponieważ jednym z najczęstszych problemów, z którymi borykają się deweloperzy, jest to, że gdy łańcuch obietnic jest nieprawidłowy lub uszkodzony, Chrome wyświetla to „domyślne” powiadomienie:

Obraz domyślnego powiadomienia w Chrome

Chrome wyświetli powiadomienie „Ta strona została zaktualizowana w tle” tylko wtedy, gdy otrzyma wiadomość push, a zdarzenie push w obsługiwanym przez usługę workerze nie wyświetli powiadomienia po zakończeniu obietnicy przekazanej do event.waitUntil().

Głównym powodem, dla którego deweloperzy wpadają w tę pułapkę, jest to, że ich kod często wywołuje funkcję self.registration.showNotification(), ale nic nie robi z obietnicą zwracaną przez tę funkcję. Może to powodować sporadyczne wyświetlanie powiadomienia domyślnego. Możemy na przykład usunąć wartość zwracaną dla funkcji self.registration.showNotification() w przykładzie powyżej, co spowoduje wyświetlenie powiadomienia.

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

Jak widać, łatwo to przeoczyć.

Jeśli zobaczysz takie powiadomienie, sprawdź łańcuchy obietnic i event.waitUntil().

W następnej sekcji omówimy, jak stylizować powiadomienia i jakie treści można wyświetlać.

Co dalej

Code labs