Zdarzenia push

Do tej pory omawialiśmy subskrypcję użytkownika i wysyłanie powiadomienia push. Następnym krokiem jest odebranie tego komunikatu 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 służący do konfigurowania detektora zdarzeń 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. Język self jest powszechnie używany w skryptach service worker. self odnosi się do zakresu globalnego, który w rodzaju window na stronie internetowej. W przypadku skryptów web worker i service worker element self odnosi się do samego workera.

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

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

Dane ze zdarzenia push można 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 warto wiedzieć o mechanizmach Service Worker, jest to, że masz niewielką kontrolę nad tym, kiedy będzie uruchamiany ich kod. Przeglądarka decyduje, kiedy ją aktywować i kiedy zakończyć. Jedynym sposobem, w jaki możesz poinformować przeglądarkę, że jestem zajęta do ważnych spraw, jest przekazanie do metody event.waitUntil() obietnic. 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 istnieje dodatkowy wymóg, aby wyświetlać powiadomienie, zanim przekazana obietnica zostanie zrealizowana.

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 nieporozumienia tego, co powinno być przekazane do waitUntil(), lub z niespełnienia obietnic.

Bardziej skomplikowany przykład z żądaniem sieciowym dotyczącym danych i śledzeniem zdarzenia push za pomocą analityki 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 również żądanie sieciowe, otrzymujemy odpowiedź i wyświetlamy powiadomienie, wykorzystując dane odpowiedzi dla tytułu i przekazu 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 service workera.

Powinniśmy się przejmować waitUntil() i tym, jak go używać, 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. Moglibyśmy na przykład usunąć zwrot związany z usługą self.registration.showNotification() w powyższym przykładzie. Pojawia się wtedy ryzyko, że zobaczymy to powiadomienie.

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 to 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

Codelabs