我想要实现的目标:
使用loader / spinner渲染页面
如果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);
});
});
在阅读spec之后,显然没有updatenotfound
之类的处理程序。看似serviceWorker.register
检查service-worker.js
是否通过运行get-newest-worker-algorithm在内部进行了更改,但我看不到通过公共API公开的类似方法。
我认为我的选择是:
onupdatefound
service-worker.js
代码触发自定义事件还有其他建议吗?
修改
我提出了一些代码,通过在SW注册和SW客户端之间使用 postMessage()
解决了这个问题(如@pate建议的那样)
以下演示尝试通过SW客户端和SW注册之间的postMessage
进行检查,但由于SW代码已缓存DEMO
修改
所以现在看起来我无法实现我想要的东西,因为:
onupdatefound
,没有任何其他内容可以通知SW中的更改activation
出现在onupdatefound
activation
update()
尚不成熟,不断变化,Starting with Chrome 46, update() returns a promise that resolves with 'undefined' if the operation completed successfully or there was no update
答案 0 :(得分:3)
Fabio提供的另一个答案不起作用。 Service Worker脚本无权访问DOM。无法从DOM中删除任何内容,或者,例如,操纵处理来自Service Worker 中的DOM元素的任何数据。该脚本单独运行,没有共享状态。
但是,您可以做的是在实际运行页面的JS和Service Worker之间发送消息。我不确定这是否是OP所要求的最佳方式,但可以用来实现它。
我自己将SW版本号保存在SW内的变量中。然后我的SW将该版本号发布到页面,页面已将其存储到浏览器的localStorage中。下次加载页面时,SW将当前版本号发布到页面,并且onmessage处理程序将其与当前存储的版本号进行比较。如果它们不相同,则SW已更新为包含在mssage中的某个版本号。之后我更新了版本号的localStorage副本并完成了这个和那个。
此流程也可以通过其他方式完成:从页面向SW发送消息,让SW回复一些内容,然后采取相应措施。
我希望我能够清楚地解释我的想法:)
答案 1 :(得分:0)
在我脑海中弹出的唯一方法是正常启动加载程序,然后在service-worker中的install函数中将其删除。我将在您的service-worker.js中试一试:
self.addEventListener('install', function(e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function(cache) {
console.log('[ServiceWorker] Caching app shell');
return cache.addAll(filesToCache);
}).then(function() {
***removeLoader();***
return self.skipWaiting();
})
);
});