在本程式碼研究室中,您將使用服務工作者來管理通知。本說明假設您已熟悉服務工作者,以及要求通知權限和傳送通知的基本概念。如需複習通知相關知識,請參閱「開始使用 Notifications API」程式碼研究室。如要進一步瞭解 Service Worker,請參閱 Matt Gaunt 的「Service Worker 簡介」。
重新混合範例應用程式,並在新分頁中查看
系統會自動封鎖內嵌 Glitch 應用程式的通知,因此您無法在本頁面上預覽該應用程式。請改用以下做法:
- 按一下「Remix to Edit」,即可編輯專案。
- 如要預覽網站,請按下「View App」。然後按下「Fullscreen」圖示 。
Glitch 應會在新分頁中開啟。
在本程式碼研究室中,請修改本頁嵌入的 Glitch 中的程式碼。重新整理含有即時應用程式的新分頁,即可查看變更內容。
熟悉範例應用程式和啟動程式碼
首先,請在新的 Chrome 分頁中查看即時應用程式:
- 按下 `Control + Shift + J` 鍵 (在 Mac 上為 `Command + Option + J` 鍵) 開啟開發人員工具。
再按一下「Console」(控制台) 分頁標籤即可。
請確認您已在「篩選」方塊旁的「層級」下拉式選單中,選取「資訊」選項。
在線上應用程式的開發人員工具控制台中,您應該會看到控制台訊息:
TODO: Implement getRegistration()
。這是您將在本程式碼研究室中實作的函式暫存程式訊息。
接下來,我們來看看這個頁面中嵌入的 Glitch 中,範例應用程式的程式碼。
在嵌入的 Glitch 中,查看
public/index.js
:您要實作的函式有四個 Stub:
registerServiceWorker
、getRegistration
、unRegisterServiceWorker
和sendNotification
。requestPermission
函式會要求使用者授權傳送通知。如果您已完成Notifications API codelab,就會發現這裡使用了requestPermission
函式。唯一的差異在於,現在也會在解決權限要求後更新使用者介面。updateUI
函式會重新整理應用程式的所有按鈕和訊息。initializePage
函式會在瀏覽器中執行服務工作者功能的功能偵測,並更新應用程式使用者介面。指令碼會等待頁面載入,然後將其初始化。
在嵌入的 Glitch 中開啟
public/service-worker.js
。顧名思義,您會在應用程式中新增程式碼,將此檔案註冊為服務工作者。
雖然應用程式尚未使用該檔案,但檔案包含一些啟動程式碼,可在服務工作者啟用時,將訊息輸出至控制台。
您會在
public/service-worker.js
中加入程式碼,以便在服務工作者收到通知時處理通知。
註冊 Service Worker
在這個步驟中,您將編寫程式碼,在使用者點選應用程式 UI 中的「Register service worker」時執行。這段程式碼會將 public/service-worker.js
註冊為服務 worker。
在內嵌的 Glitch 編輯器中開啟
public/index.js
。使用以下程式碼取代registerServiceWorker
函式:// Use the Service Worker API to register a service worker. async function registerServiceWorker() { await navigator.serviceWorker.register('./service-worker.js') updateUI(); }
請注意,
registerServiceWorker
會使用async function
宣告,讓處理承諾更方便。這樣一來,您就可以await
Promise
的解析值。舉例來說,上述函式會在更新 UI 前,等待註冊服務 worker 的結果。詳情請參閱 MDN 上的await
。使用者現在可以註冊服務工作者,因此您可以取得服務工作者註冊物件的參照。在
public/index.js
中,將getRegistration
函式替換為以下程式碼:// Get the current service worker registration. function getRegistration() { return navigator.serviceWorker.getRegistration(); }
上述函式會使用 Service Worker API 取得目前的服務 worker 註冊 (如有)。這麼做可讓您更輕鬆地取得服務工作者註冊的參照。
如要完成 Service Worker 註冊功能,請新增程式碼來取消註冊 Service Worker。使用以下程式碼取代
unRegisterServiceWorker
函式:// Unregister a service worker, then update the UI. async function unRegisterServiceWorker() { // Get a reference to the service worker registration. let registration = await getRegistration(); // Await the outcome of the unregistration attempt // so that the UI update is not superceded by a // returning Promise. await registration.unregister(); updateUI(); }
在您觀看直播應用程式的分頁中,重新載入頁面。「Register service worker」和「Unregister service worker」按鈕現在應該可以正常運作。
傳送通知至服務工作者
在這個步驟中,您將編寫程式碼,在使用者點選應用程式 UI 中的「Send a notification」時執行。這段程式碼會建立通知、檢查服務工作者是否已註冊,然後使用服務工作者的 postMessage
方法將通知傳送給服務工作者。
在內嵌的 Glitch 編輯器中,開啟 public/index.js
,然後將 sendNotification
函式替換為以下程式碼:
// Create and send a test notification to the service worker.
async function sendNotification() {
// Use a random number as part of the notification data
// (so you can tell the notifications apart during testing!)
let randy = Math.floor(Math.random() * 100);
let notification = {
title: 'Test ' + randy,
options: { body: 'Test body ' + randy }
};
// Get a reference to the service worker registration.
let registration = await getRegistration();
// Check that the service worker registration exists.
if (registration) {
// Check that a service worker controller exists before
// trying to access the postMessage method.
if (navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.postMessage(notification);
} else {
console.log('No service worker controller found. Try a soft reload.');
}
}
}
以下是該程式碼的運作方式:
sendNotification
是個非同步函式,因此您可以使用await
取得服務工作者註冊的參照。服務工作站的
postMessage
方法會將應用程式中的資料傳送至服務工作站。詳情請參閱 postMessage 的 MDN 說明文件。程式碼會先檢查是否有
navigator.serviceWorker.controller
屬性,再嘗試存取postMessage
函式。如果沒有有效的 Service Worker,或是網頁已強制重新整理 (Shift+
Reload),navigator.serviceWorker.controller
就會是null
。詳情請參閱 MDN 上的 ServiceWorker 控制器說明文件。
在服務工作站中處理通知
在這個步驟中,您將在服務工作者中編寫程式碼,以便處理發布至該服務工作者的訊息,並向使用者顯示通知。
在內嵌的 Glitch 編輯器中開啟 public/service-worker.js
。在檔案結尾新增下列程式碼:
// Show notification when received
self.addEventListener('message', (event) => {
let notification = event.data;
self.registration.showNotification(
notification.title,
notification.options
).catch((error) => {
console.log(error);
});
});
以下簡要說明:
self
是服務工作者本身的參照。雖然服務工作者現在會處理顯示通知的作業,但主要應用程式 UI 仍負責取得使用者的通知權限。如果未授予權限,
showNotification
傳回的承諾會遭到拒絕。上述程式碼使用catch
區塊,避免未偵測到的Promise
拒絕錯誤,並以更妥善的方式處理這項錯誤。
如果卡住了,請參閱 glitch.com/edit/#!/codelab-notifications-service-worker-completed 查看完整程式碼。
請繼續參閱本系列的下一篇程式碼研究室:建構推播通知伺服器。