此時,我們介紹了訂閱使用者及傳送推送訊息。接下來,您必須在使用者的裝置上接收這則推播訊息,並顯示通知 (以及執行其他可能需要執行的工作)。
Push 事件
收到訊息後,系統會在服務工作站中發布推送事件。
用來設定推送事件監聽器的程式碼應與您在 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
。但對網路工作站和服務工作站而言,self
指的是工作站本身。
在上述範例中,self.addEventListener()
可視為在服務工作者本身新增事件監聽器。
在推送事件範例中,我們會檢查是否有任何資料,並將內容輸出至控制台。
您還可以透過其他方式剖析推送事件的資料:
// 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()
。
Wait Until
關於服務工作站,您必須瞭解的一件事是,您幾乎無法控制服務工作站程式碼的執行時間。瀏覽器會決定何時喚醒及終止該服務。您唯一能向瀏覽器表示「我正忙著處理重要事項」的方法,就是將承諾傳遞至 event.waitUntil()
方法。如此一來,瀏覽器就會維持服務工作處理程序,直到傳入的承諾完成為止。
對於推播事件,您必須在傳入的承諾已完成時才可顯示通知,這是額外規定。
以下是顯示通知的基本範例:
self.addEventListener('push', function(event) {
const promiseChain = self.registration.showNotification('Hello, World.');
event.waitUntil(promiseChain);
});
呼叫 self.registration.showNotification()
是向使用者顯示通知的方法,並會傳回承諾,在通知顯示後會解析。
為了讓這個範例盡可能清楚,我將這個承諾指派給名為 promiseChain
的變數。然後傳入 event.waitUntil()
。我知道這會產生大量文字,但我發現許多問題都是因為誤解應傳入 waitUntil()
的內容,或是因為承諾鏈條中斷而產生。
一個更複雜的範例包含使用網路要求的資料,以及使用分析工具追蹤推送事件的例子,如下所示:
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 會顯示這個「預設」通知:
只有在收到推播訊息,且服務工作者中的推播事件在傳遞至 event.waitUntil()
的承諾完成後「不會」顯示通知時,Chrome 才會顯示「This site has been updated in the background」通知。
開發人員遇到這個問題的主因是,他們的程式碼通常會呼叫 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()
。
在下一節中,我們將探討如何設定通知樣式,以及可顯示的內容。