我想要实现的目标:
使用加载器/旋转器渲染页面
如果已经注册并激活了
service-worker.js
,则检查是否有更新- 如果没有更新,则移除加载器
- 如果发现新版本
updatefound
,则重新加载页面
- 否则注册
service-worker.js
- 当
updatefound
,即安装了新的版本时,移除加载器
- 当
我正在使用sw-precache
模块来生成service-worker.js
,并遵循以下注册代码:
window.addEventListener('load', function() {
// show loader
addLoader();
navigator.serviceWorker.register('service-worker.js')
.then(function(swRegistration) {
// react to changes in `service-worker.js`
swRegistration.onupdatefound = function() {
var installingWorker = swRegistration.installing;
installingWorker.onstatechange = function() {
if(installingWorker.state === 'installed' && navigator.serviceWorker.controller){
// updated content installed
window.location.reload();
} else if (installingWorker.state === 'installed'){
// new sw registered and content cached
removeLoader();
}
};
}
if(swRegistration.active){
// here I know that `service-worker.js` was already installed
// but not sure it there are changes
// If there are no changes it is the last thing I can check
// AFAIK no events are fired afterwards
}
})
.catch(function(e) {
console.error('Error during service worker registration:', e);
});
});
阅读规范后,我发现似乎没有像updatenotfound
这样的处理程序。看起来serviceWorker.register
会通过运行get-newest-worker-algorithm检查service-worker.js
是否在内部发生了更改,但我没有看到类似的方法通过公共API暴露出来。
我认为我的选项是:
- 等待服务工作者注册变为活动状态后几秒钟,以查看是否触发了
onupdatefound
如果未更新缓存,则从service-worker.js
代码中触发自定义事件
还有其他建议吗?
编辑:
我想出了一些代码,通过在SW注册和SW客户端之间使用postMessage()
解决了这个问题(如@pate建议的那样)
以下演示试图通过postMessage
在SW客户端和SW注册之间进行检查,但由于SW代码已被缓存,因此失败DEMO
编辑:
到目前为止,看起来我不能实现我想要的,因为:
- 当服务工作者处于活动状态时,您无法通过在SW中评估某些代码来检查更新-这仍然是相同的缓存SW,没有任何更改。
- 您需要等待
onupdatefound
,没有其他可以通知SW更改的方式了 - 比
onupdatefound
更老的SW的activation
会先发生 - 如果没有变化,则在
activation
之后不会触发任何内容 - SW注册
update()
还不成熟,一直在变化,从Chrome 46开始,如果操作成功或没有更新,则update()会返回一个解析为'undefined'
的承诺 - 设置超时以延迟视图渲染是次优的,因为没有明确的答案可以设置多长时间,它也取决于SW大小