在此 Codelab 中,您将使用服务工作线程来管理通知。此处的说明假定您已熟悉 Service Worker,以及请求通知权限和发送通知的基本知识。 如果您需要复习通知,请参阅通知 API 使用入门 codelab。如需详细了解 Service Worker,请参阅 Matt Gaunt 的 Service Worker 简介。
熟悉示例应用和起始代码
首先,在新的 Chrome 标签页中查看实时应用:
- 按 `Control+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
点击控制台标签页。
确保在过滤条件框旁边的级别下拉菜单中选择了 Info 选项。
在实时应用的开发者工具控制台中,您应该会看到一条控制台消息:
TODO: Implement getRegistration()
。这是您将在此 Codelab 中实现的函数桩的消息。
现在,我们来看一下示例应用的代码。
请看
public/index.js
:您将实现的函数有四个桩:
registerServiceWorker
、getRegistration
、unRegisterServiceWorker
和sendNotification
。requestPermission
函数请求用户授予发送通知的权限。如果您完成了“开始使用 Notifications API”Codelab,您会注意到此处使用了其requestPermission
函数。唯一的区别在于,它现在还会在解决权限请求后更新界面。updateUI
函数会刷新应用的所有按钮和消息。initializePage
函数用于在浏览器中检测 Service Worker 功能,并更新应用界面。脚本会等待页面加载完毕,然后对其进行初始化。
打开
public/service-worker.js
。顾名思义,您需要向应用添加代码,以将此文件注册为服务工作器。
虽然该文件尚未被应用使用,但它包含一些启动代码,可在服务工作线程激活时向控制台输出一条消息。
您将向
public/service-worker.js
添加代码,以便在服务工作线程收到通知时处理通知。
注册 Service Worker
在此步骤中,您将编写在用户点击应用界面中的 Register service worker 时运行的代码。此代码会将 public/service-worker.js
注册为服务工作线程。
打开
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
声明来更方便地处理 promise。这样,您就可以await
Promise
的已解析值。例如,上述函数会等待注册服务工作线程的结果,然后再更新界面。如需了解详情,请参阅 MDN 上的await
。现在,用户可以注册 Service Worker,您可以获取对 Service Worker 注册对象的引用。在
public/index.js
中,将getRegistration
函数替换为以下代码:// Get the current service worker registration. function getRegistration() { return navigator.serviceWorker.getRegistration(); }
上述函数使用 Service Worker API 获取当前 Service 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(); }
在您查看实时应用的标签页中,重新加载页面。注册 Service Worker 和取消注册 Service Worker 按钮现在应该可以正常工作了。
向 Service Worker 发送通知
在此步骤中,您将编写在用户点击应用界面中的 Send a notification 时运行的代码。此代码将创建一个通知,检查是否已注册服务工作线程,然后使用服务工作线程的 postMessage
方法将通知发送给该服务工作线程。
打开 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
获取对 Service Worker 注册的引用。服务工作线程的
postMessage
方法用于将数据从应用发送到服务工作线程。如需了解详情,请参阅 MDN 上有关 postMessage 的文档。该代码会先检查是否存在
navigator.serviceWorker.controller
属性,然后再尝试访问postMessage
函数。如果没有有效的服务工作线程,或者网页已强制刷新(Shift+
重新加载),则navigator.serviceWorker.controller
为null
。如需了解详情,请参阅 MDN 上的 ServiceWorker 控制器文档。
在 Service Worker 中处理通知
在此步骤中,您将在服务工作线程中编写代码,以处理发布给它的消息并向用户显示通知。
打开 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
是对服务工作线程本身的引用。虽然服务工作线程现在负责显示通知,但主应用界面仍负责从用户那里获取通知权限。如果未授予权限,则
showNotification
返回的 promise 会被拒绝。上述代码使用catch
块来避免未捕获的Promise
拒绝错误,并更妥当地处理此错误。
继续学习本系列中的下一个 Codelab:构建推送通知服务器。