到目前为止,我们已经介绍了如何订阅用户和发送推送消息。下一步是 在用户设备上接收此推送消息并显示通知 我们想要做的工作)。
推送事件
收到消息后,会在 Service Worker 中分派推送事件。
用于设置推送事件监听器的代码应该与任何其他事件非常相似 使用 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.');
}
});
对于大多数刚接触 Service Worker 的开发者来说,此代码最奇怪的那一部分是 self
变量。self
常用于 Web Worker(即 Service Worker)。self
是指
全局范围,有点像网页中的 window
。但对于 Web Worker 和 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()
。
等待到
关于 Service Worker,您需要了解的一点是,您几乎无法控制
Service Worker 代码将要运行浏览器决定何时唤醒和何时唤醒浏览器
终止它。您只能告诉浏览器“嘿,我正忙得不可开交
就是将 promise 传递到 event.waitUntil()
方法中。这样一来,浏览器就会
使 Service Worker 一直运行,直到您传入的 promise 得到解决。
使用推送事件时,还有一项额外要求:您必须先显示通知, 你传入的 promise 已得到解决。
下面是一个显示通知的基本示例:
self.addEventListener('push', function(event) {
const promiseChain = self.registration.showNotification('Hello, World.');
event.waitUntil(promiseChain);
});
调用 self.registration.showNotification()
是向用户显示通知的方法,
用户将返回一个 promise,该 promise 会在显示通知后解析。
为了使此示例尽可能清晰,我将此 promise 分配给了
名为 promiseChain
的变量。然后将其传入 event.waitUntil()
。我知道这是
非常冗长,但我已经看到了
误解了应向 waitUntil()
传递什么数据,或由于 promise 出错而传递什么数据
链。
一个更复杂的示例,其中包含针对数据的网络请求以及使用 可能如下所示:
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);
});
在这里,我们将调用一个返回 promise pushReceivedTracking()
的函数,
在本示例中,我们可以假装将发出网络请求
分析服务提供商我们还将发出网络请求,获取
响应,并使用标题和响应数据显示通知
消息。
在这两个任务同时完成时,我们可以将 Service Worker
这些 promise 与 Promise.all()
结合使用。生成的 promise 会传递到 event.waitUntil()
中
这意味着浏览器会等到两个 promise 都完成后再检查通知
并终止 Service Worker。
我们之所以应该关注 waitUntil()
及其使用方式,是因为
开发者面临的常见问题是:如果 promise 链不正确 / 已损坏,Chrome 将会
显示此“默认”通知:
![Chrome 中默认通知的图片](https://web.developers.google.cn/static/articles/push-notifications-handling-messages/image/an-image-the-default-not-ec0a0feda0315.png?authuser=7&hl=ro)
Chrome 仅会显示“此网站已在后台更新”。触发
收到推送消息后,Service Worker 中的推送事件没有显示
在传递给 event.waitUntil()
的 promise 完成后发出通知。
开发者遇到这一问题的主要原因是
经常调用 self.registration.showNotification()
,但并不执行
返回任何与其返回的 promise 相同的内容。间歇性地会导致系统显示默认通知
。例如,我们可以移除
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);
});
这样,您就会明白这是多么容易被遗忘的事了。
请注意,如果您看到了该通知,请检查您的 promise 链和 event.waitUntil()
。
在下一部分,我们将介绍如何设置通知样式, 我们可以展示哪些内容