问题描述
我想要实现的目标:
使用加载器/微调器渲染页面
render page with loader/spinner
如果 service-worker.js
已注册并处于活动状态,则检查更新
if service-worker.js
is registered and active, then check for updates
- 如果没有更新,则删除加载器
- 如果安装了
updatefound
和新版本,则重新加载页面
- if no updates, then remove loader
- if
updatefound
and new version installed, then reload the page
- 当
updatefound
,意味着安装了新的,移除加载器
- when
updatefound
, meaning new one was installed, remove loader
我正在使用 sw-precache
模块来生成 service-worker.js
和以下注册代码:
I am using sw-precache
module for me to generate service-worker.js
and following registration code:
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
通过运行 ,但我看不到通过公共 api 公开的类似方法.
After reading the spec it is clear that there are no handlers for something like
updatenotfound
. Looks like serviceWorker.register
checks if service-worker.js
changed internally by running get-newest-worker-algorithm, but I cannot see similar methods exposed via public api.
我认为我的选择是:
在 Service Worker 注册激活后等待几秒钟,看看
onupdatefound
是否被触发
wait for couple of seconds after service worker registration becomes active to see if
onupdatefound
is fired
还有其他建议吗?
以下演示尝试通过
postMessage
在软件客户端和软件注册之间实现检查,但由于软件代码已经缓存而失败演示
Following demo tries to achieve checks through
postMessage
between SW client and SW registration, but fails as SW code is already cached DEMO
所以现在看来我无法实现我想要的,因为:
So by now it looks like I cannot implement what I want because:
当 Service Worker 处于活动状态时,您无法通过评估 SW 中的某些代码来检查更新 - 这仍然是相同的缓存 SW,没有任何更改
你需要等待
onupdatefound
,没有其他东西会通知软件的变化activation
旧软件的onupdatefound
如果没有变化,在
激活
- 软件注册
update()
不成熟,不断变化,从 Chrome 46 开始,update() 返回一个 promise,如果操作成功完成或没有更新,则返回一个 'undefined' 解析
- 设置超时以推迟视图渲染是次优的,因为对于应该设置多长时间没有明确的答案,这也取决于软件大小
后什么也不会触发
when service worker is active you cannot check for updates by evaluating some code in SW - this is still the same cached SW, no changes there
you need to wait for
onupdatefound
, there is nothing else that will notify of changes in SWactivation
of older SW comes beforeonupdatefound
if there is no change, nothing fires after
activation
SW registration
update()
is immature, keeps changing,Starting with Chrome 46, update() returns a promise that resolves with 'undefined' if the operation completed successfully or there was no update
setting timeout to postpone view rendering is suboptimal as there is no clear answer to how long should it be set to, it depends on SW size as well
推荐答案
Fabio 提供的另一个答案不起作用.Service Worker 脚本无法访问 DOM.不可能从 DOM 中删除任何内容,或者,例如,从 Service Worker 内部操作处理 DOM 元素的任何数据.该脚本单独运行,没有共享状态.
The other answer, provided by Fabio, doesn't work. The Service Worker script has no access to the DOM. It's not possible to remove anything from the DOM or, for instance, manipulate any data that is handling DOM elements from inside the Service Worker. That script runs separately with no shared state.
不过,您可以做的是在实际运行页面的 JS 和 Service Worker 之间发送消息.我不确定这是否是执行 OP 要求但可用于实现它的最佳方法.
What you can do, though, is send messages between the actual page-running JS and the Service Worker. I'm not sure if this is the best possible way to do what the OP is asking but can be used to achieve it.
在页面上注册一个 onmessage 处理程序
将来自软件的激活或安装事件的消息发送到页面
在页面上收到消息时采取相应的行动
我自己将软件版本号保存在软件内部的一个变量中.然后,我的软件将该版本号发布到页面,页面将其存储到浏览器的 localStorage 中.下次加载页面时,软件会将其当前版本号发布到页面,并且 onmessage 处理程序将其与当前存储的版本号进行比较.如果它们不相同,则软件已更新为包含在 mssage 中的某个版本号.在那之后,我更新了版本号的 localStorage 副本并完成了这个和那个.
I have myself kept SW version number in a variable inside the SW. My SW has then posted that version number to the page and the page has stored it into the localStorage of the browser. The next time the page is loaded SW posts it current version number to the page and the onmessage handler compares it to the currently stored version number. If they are not the same, then the SW has been updated to some version number that was included in the mssage. After that I've updated the localStorage copy of the version number and done this and that.
这个流程也可以用另一种方式来完成:从页面向软件发送消息,让软件回复,然后采取相应的行动.
This flow could also be done in the other way around: send a message from the page to the SW and let SW answer something back, then act accordingly.
我希望我能够清楚地解释我的想法:)
I hope I was able to explain my thoughts clearly :)
这篇关于如何:ServiceWorker 检查是否准备好更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!