我正在尝试实现一个为Web应用程序执行推送通知的服务工作者。我希望系统具有弹性,因为它不断发送推送通知,而无需用户定期与应用程序进行交互。为此,我正在关注pushsubscriptionchange
事件,但我不确定如何在服务工作者的有限约束内工作。
我当前的代码捕获此事件,创建新订阅并通过postMessage
将其发送回客户端。然后客户端调用我的后端并注册新的订阅端点。
这似乎是最优雅的方式,除了我认为它需要一个打开的标签。如果用户几天没有办理登机手续但仍然对获取推送通知感兴趣,那么现有订阅最终会超时,并且无法通知应用有关新获得的端点的信息。
然后,我有了将REST端点添加到接受更新订阅的应用程序的想法。一个复杂的问题是该应用程序使用Meteor,因此服务工作者无法访问其自身的基础设施(例如DDP协议)。
我的想法是每当添加新订阅时生成UUID作为令牌。然后,服务工作者可以fetch
将端点作为查询参数传递并发送新的端点/密钥。然后创建一个新令牌,删除旧令牌,并注册新推送端点。
不幸的是,我不确定如何以客户端和服务工作者可以共享的方式存储令牌。服务人员无法使用本地存储。缓存API似乎针对实际请求,而不是简单的键/值。 IndexDB可供服务工作者使用,但我真的只想存储一个键入“pushEndpointToken”之类的UUID。除了打开数据库并为此单个键/值声明模式之外,我真的没有其他选择吗?
有没有第三种方法我不考虑?我只想确保我的应用程序始终具有有效的推送端点,只要用户想要从其接收通知。
感谢。
答案 0 :(得分:0)
<强>更新强>
当服务工作程序停止并稍后唤醒时,运行时变量将丢失。您需要使用持久存储,例如IndexedDB或cookie(将令牌附加到请求)。
我可以推荐idb-keyval - 我在app(写)和服务工作者(读)之间共享一个数据库。
老答案:您可以使用PostMessage API将令牌发送到服务工作者 这是一个概念,我还在努力
<强>服务worker.js:强>
const runtimeVars = {
token: undefined,
}
self.addEventListener('message', event => {
// Probably no need for this check
if (event.origin !== self.origin) {
return
}
if (event.data.token) {
runtimeVars.token = event.data.token
}
})
self.addEventListener('pushsubscriptionchange', event => {
// Fire unregister request with runtimeVars.token
})
<强> app.js 强>
const controller = window.navigator.serviceWorker.controller
if (controller)
// At app dispatch
controller.postMessage({token: localStorage.getItem('token'})
// After login pass API token to service worker
controller.postMessage({token})
// After logout, nullify token
controller.postMessage({token: undefined})
}