Service worker 服务人员在Chrome中处于等待状态
我正在和Vue一起做水疗。我想在用户导航到特定页面时更新为新的服务人员。由于用户的视图已更改(本视频中讨论的模式:),因此需要进行刷新 我有一个问题,有时(很少)服务人员在呼叫skipWaiting时无法激活。调用是正确的,即使在Chrome中,我也会得到一个当前服务人员停止的响应(参见动画GIF),但是如果该服务人员再次开始运行,而不是等待的服务人员 一段时间(1-2分钟)后,服务人员突然被激活。不是你想要的情况,因为当用户可能处于某个活动的中间时,它会突然发生。 此外,在这种情况下,我无法再次调用skipWaiting(通过执行多个导航)来激活服务人员。服务人员收到了,但什么也没发生。它停留在“等待激活”状态。当我在Chrome中按skipWaiting时,它就工作了 我不知道出了什么问题。这是Chrome、workbox或其他产品的问题吗 最接近这个话题的是: 我使用Vue.js,但我不依赖服务工作者的pwa插件。我使用workbox网页包插件 我编辑了下面的示例代码,最小的代码可能没有很好地显示问题 在main.js中:Service worker 服务人员在Chrome中处于等待状态,service-worker,workbox,Service Worker,Workbox,我正在和Vue一起做水疗。我想在用户导航到特定页面时更新为新的服务人员。由于用户的视图已更改(本视频中讨论的模式:),因此需要进行刷新 我有一个问题,有时(很少)服务人员在呼叫skipWaiting时无法激活。调用是正确的,即使在Chrome中,我也会得到一个当前服务人员停止的响应(参见动画GIF),但是如果该服务人员再次开始运行,而不是等待的服务人员 一段时间(1-2分钟)后,服务人员突然被激活。不是你想要的情况,因为当用户可能处于某个活动的中间时,它会突然发生。 此外,在这种情况下,我无法
let sw = await navigator.serviceWorker.register("/service-worker.js", {
updateViaCache: "none",
});
let firstSw = false;
navigator.serviceWorker.addEventListener("controllerchange", () => {
// no need to refresh when the first sw controls the page, we solve this with clientsClaim
// this makes sure when multiple-tabs are open all refresh
if (!firstSw) {
window.location.reload();
}
});
sw.onupdatefound = () => {
const installingWorker = sw.installing;
installingWorker.onstatechange = async () => {
console.log("installing worker state-change: " + installingWorker.state);
if (installingWorker.state === "installed") {
if (navigator.serviceWorker.controller) {
firstSw = false;
// set the waiting service-worker in the store
// so we can update it and refresh the page on navigation
await store.dispatch("setWaitingSW", sw.waiting);
} else {
console.log("First sw available");
firstSw = true;
}
}
};
};
在router.js中:
// after navigation to specific routes we check for a waiting service-worker.
router.afterEach(async (to) => {
if (to.name == "specificpage") {
let waitingSw = store.getters["getWaitingSW"];
if (waitingSw) {
waitingSw.postMessage("SKIP_WAITING");
// clean the store, because we might have changed our data model
await store.dispatch("cleanLocalForage");
}
}
});
在service-worker.js中:
self.addEventListener("message", event => {
if (event.data === "SKIP_WAITING") {
console.log("sw received skip waiting");
self.skipWaiting();
}
});
我不确定
let sw = await navigator.serviceWorker.register("/service-worker.js", {updateViaCache: "none"});
if (sw.waiting) {
sw.waiting.postMessage("SKIP_WAITING");
}
是本例中所需的代码。您的if(sw.waiting)
检查仅评估一次,评估时新注册的服务人员可能仍处于安装
状态。如果是这种情况,则在初始评估时,sw.waiting
将是false
-y,尽管在一小段时间后可能是true
-y
相反,我建议您遵循所演示的模式,在该模式中,您可以明确地侦听服务人员在注册时输入等待
。该示例使用工作盒窗口
库来覆盖一些细节
如果您不想使用
工作盒窗口
,则应按照检查查看注册后是否设置了sw.安装
;如果是,请收听sw.installing
上的statechange
事件,以检测它何时“安装”。一旦发生这种情况,sw.waiting
应设置为新安装的服务人员,此时,您可以postMessage()
。skipWaiting()
不是即时的。如果当前服务工作者正在进行活动回迁,则不会中断这些回迁。如果您看到skipWaiting()
花费了很长时间,我猜您有一些长期运行的HTTP连接将旧的服务工作者保留在适当的位置。我知道我只检查了一次。我想用最简单的例子。如果有一个等待更新的工作人员,则在用户刷新页面的情况下运行此操作。您的if(sw.waiting)检查只评估一次,评估时新注册的服务工作者可能仍处于安装状态。它不应该在Chrome中给出“安装”状态吗。我想当服务人员处于“等待激活”状态时,它不处于安装状态?或者这一假设是错误的?我会看看你的建议。谢谢。对于该用例,在运行时,sw.installing
可能会被设置为相关的软件,而sw.waiting
根本不会被设置。不久之后,一旦更新的软件完成安装,将设置SW.waiting
。所以这里有一个竞赛条件,你真的需要听事件而不是做一次性检查。我修改了示例代码以更好地解释这种情况。我在听一些事件,但我想分享一下发生这种情况的最基本情况。谢谢。我如何检测那些长时间运行的连接?以及你如何处理你和苏玛在视频中描述的这种模式。因为当在页面导航上进行Skipwait时,您希望它立即发生,对吗?或者你只是接受这个用例的发生?我知道Safari只是中止正在进行的http连接,知道Chrome为什么使用另一种模式吗?