Zdarzenia push

W tym momencie omówiliśmy subskrybowanie użytkownika i wysyłanie wiadomości push. Następnym krokiem jest odebranie tej wiadomości push na urządzeniu użytkownika i wyświetlenie jej powiadomienia (oraz wykonanie innych czynności, które możemy wykonywać).

Zdarzenie push

Odebranie wiadomości spowoduje wysłanie zdarzenia push przez skrypt service worker.

Kod konfiguracji odbiornika zdarzeń push powinien być podobny do kodu innych odbiorników, które pisze się w JavaScripcie:

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 fragmentem tego kodu dla większości programistów, którzy dopiero zaczynają korzystać z skryptów service worker, jest zmienna self. Język self jest powszechnie używany w skryptach Web Workers, czyli skrytkach service worker. self odnosi się do zakresu globalnego, podobnie jak window na stronie internetowej. Natomiast w przypadku instancji roboczych i skryptów service worker self odnosi się do samych instancji roboczych.

W powyższym przykładzie self.addEventListener() można traktować jako dodawanie detektora zdarzeń do samego skryptu service worker.

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

Dane ze zdarzenia push możesz 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ść użytkowników korzysta z json() lub text() w zależności od tego, czego oczekują od aplikacji.

W tym przykładzie pokazujemy, jak dodać detektor zdarzeń push i uzyskać dostęp do danych, ale brakuje w nim 2 bardzo ważnych funkcji. Nie wyświetla powiadomienia i nie korzysta z event.waitUntil().

Zaczekaj do

Jedną z rzeczy, które trzeba wiedzieć o mechanizmach Service Worker, jest fakt, że nie masz zbyt wielu kontroli nad tym, kiedy uruchamia się ich kod. Przeglądarka decyduje, kiedy ją wybudzić i zakończyć. Jedynym sposobem na powiedzenie przeglądarce „Hej, jestem bardzo zajęta wykonywaniem ważnych czynności”, polega na przekazaniu obietnicy do metody event.waitUntil(). Dzięki temu przeglądarka będzie utrzymywać mechanizm Service Worker w swoim działaniu, dopóki przekazywana obietnica nie zostanie osiągnięta.

W przypadku zdarzeń push występuje dodatkowy wymóg, dzięki któremu musisz wyświetlić powiadomienie, zanim przekazana przez Ciebie obietnica zostanie zrealizowana.

Oto podstawowy przykład 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 powoduje wyświetlenie użytkownikowi powiadomienia i zwraca obietnicę rozwiązania problemu po jego wyświetleniu.

Aby ten przykład był jak najbardziej zrozumiały, przypisałem tę obietnicę do zmiennej o nazwie promiseChain. Dane są następnie przekazywane do interfejsu event.waitUntil(). Wiem, że to bardzo szczegółowe informacje, ale znam wiele problemów, które przełożyły się na niezrozumienie, jakie dane należy przekazać do usługi waitUntil(), lub w wyniku przerwanych łańcuchów obietnic.

Bardziej skomplikowany przykład z żądaniem sieciowym o dane 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);
});

Wywołujemy tu funkcję zwracającą obietnicę pushReceivedTracking(), która na potrzeby tego przykładu może udawać żądanie sieciowe do naszego dostawcy usług analitycznych. Wysyłamy też żądanie sieciowe, otrzymujemy odpowiedź i wyświetlamy powiadomienie wykorzystujące dane odpowiedzi dotyczące tytułu i wiadomości powiadomienia.

Łącząc te obietnice z funkcją Promise.all(), możemy mieć pewność, że skrypt service worker będzie działał, gdy oba te zadania zostaną wykonane. Wynikowa obietnica jest przekazywana do funkcji event.waitUntil(), co oznacza, że przeglądarka zaczeka, aż obie obie obietnice się zakończą, zanim sprawdzi, czy zostało wyświetlone powiadomienie, i zakończy działanie skryptu service worker.

Jednym z najczęstszych problemów deweloperów dotyczących właściwości waitUntil() i sposobu jej używania 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 pokaże powiadomienie „Ta witryna została zaktualizowana w tle” tylko wtedy, gdy otrzyma wiadomość push, a zdarzenie push w skrypcie service worker nie pokaże powiadomienia po zakończeniu obietnicy przekazanej do event.waitUntil().

Główną przyczyną tego problemu jest to, że ich kod często wywołuje funkcję self.registration.showNotification(), ale nie wykonuje niczego, co obiecuje. Z tego powodu z czasem wyświetlane jest powiadomienie domyślne. W powyższym przykładzie możemy usunąć na przykład zwracaną wartość self.registration.showNotification(), przez co zwiększamy ryzyko wyświetlenia tego 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);
});

Wiesz, jak łatwo przegapić coś.

Pamiętaj, że jeśli zobaczysz to powiadomienie, sprawdź łańcuchy obietnic i event.waitUntil().

W następnej sekcji dowiemy się, jak dodać styl powiadomień i jakie treści możemy wyświetlać.

Co dalej

Laboratoria kodu