推送事件

Matt Gaunt

現在,我們介紹了使用者的訂閱流程,並傳送推送訊息。下一步是在使用者的裝置上接收此推送訊息,並顯示通知 (以及其他我們想要執行的作業)。

推送事件

接收訊息後,系統就會在您的服務工作處理程序中分派推送事件。

設定推送事件監聽器的程式碼應與您用 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.');
    }
});

對大多數服務工作站新手開發人員而言,這段程式碼的最古老是 self 變數。self 經常用於網路工作站,也就是 Service Worker。self 是指全域範圍,就像網頁中的 window 一樣。但如果是網路工作站和 Service Worker,self 指的是 worker 本身。

在上述範例中,self.addEventListener() 可視為為 Service Worker 新增事件監聽器。

在推送事件範例中,我們會檢查是否有任何資料,並將內容輸出至控制台。

您還可以透過其他方式剖析推送事件的資料:

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

大部分人會使用 json()text(),取決於他們希望應用程式得到的內容。

本範例說明如何新增推送事件監聽器,以及如何存取資料,但缺少兩項功能。未顯示通知,也沒有使用 event.waitUntil()

等待時間:

需要瞭解的其中一個事項是,您無法控制服務工作站程式碼何時執行。瀏覽器會判斷喚醒時間和終止時間的時間。您可以藉由將承諾傳遞至 event.waitUntil() 方法,讓瀏覽器知道「嘿,我很忙,忙著處理重要工作」。如此一來,瀏覽器就會讓 Service Worker 持續運作,直到您傳入的承諾會維持不變為止。

使用推送事件時,您必須另外顯示通知,才能保證傳入的 promise。

以下是顯示通知的基本範例:

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

    event.waitUntil(promiseChain);
});

呼叫 self.registration.showNotification() 的方法可向使用者顯示通知,並會傳回承諾在顯示通知後立即解決的問題。

為了讓這個範例盡可能清楚明瞭,我已經將這個承諾項目指派給名為 promiseChain 的變數。這會傳遞至 event.waitUntil()。我知道這部分非常冗長,但我發現許多問題因為誤解了應傳遞至 waitUntil() 中,或是因為已毀損的 Proto 鏈而造成的。

這類範例比較複雜,像是提出資料網路要求,以及利用數據分析追蹤推送事件,如下所示:

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

我們在此呼叫一個傳回承諾 pushReceivedTracking() 的函式,為了達到這個範例,可以假定會向我們的分析供應商發出網路要求。我們也會發出網路要求,取得回應,並使用通知標題與訊息的回應資料來顯示通知。

我們可以結合這些承諾與 Promise.all(),確保服務工作站在執行這兩項工作時保持運作。結果保證會傳遞至 event.waitUntil(),這表示瀏覽器會等到兩次承諾都完成後,才會檢查通知是否已顯示,並終止 Service Worker。

我們應該要重視 waitUntil() 和使用方式,因為開發人員最常遇到的其中一個問題是,入侵鏈結不正確 / 無效時,Chrome 會顯示這則「預設」通知:

Chrome 預設通知的圖片

Chrome 只會顯示「這個網站已在背景更新過」通知。當收到推送訊息時,服務工作處理程序中的推送事件也不會在承諾傳遞至 event.waitUntil() 時顯示通知。

開發人員被發現,主要是因為他們的程式碼通常會呼叫 self.registration.showNotification(),但「並未」執行任何承諾傳回時的行為。這會間歇性導致顯示預設通知。舉例來說,我們可以移除上例中 self.registration.showNotification() 的傳回,而收到這則通知的風險。

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

看看它有多容易錯過的事物。

提醒您,如果看到這則通知,請查看承諾鏈和 event.waitUntil()

在下一節中,我們將探討如何為通知設定樣式,以及可以顯示的內容。

後續步驟

程式碼研究室