Service worker 服务人员在Chrome中处于等待状态

Service worker 服务人员在Chrome中处于等待状态,service-worker,workbox,Service Worker,Workbox,我正在和Vue一起做水疗。我想在用户导航到特定页面时更新为新的服务人员。由于用户的视图已更改(本视频中讨论的模式:),因此需要进行刷新 我有一个问题,有时(很少)服务人员在呼叫skipWaiting时无法激活。调用是正确的,即使在Chrome中,我也会得到一个当前服务人员停止的响应(参见动画GIF),但是如果该服务人员再次开始运行,而不是等待的服务人员 一段时间(1-2分钟)后,服务人员突然被激活。不是你想要的情况,因为当用户可能处于某个活动的中间时,它会突然发生。 此外,在这种情况下,我无法

我正在和Vue一起做水疗。我想在用户导航到特定页面时更新为新的服务人员。由于用户的视图已更改(本视频中讨论的模式:),因此需要进行刷新

我有一个问题,有时(很少)服务人员在呼叫skipWaiting时无法激活。调用是正确的,即使在Chrome中,我也会得到一个当前服务人员停止的响应(参见动画GIF),但是如果该服务人员再次开始运行,而不是等待的服务人员

一段时间(1-2分钟)后,服务人员突然被激活。不是你想要的情况,因为当用户可能处于某个活动的中间时,它会突然发生。

此外,在这种情况下,我无法再次调用skipWaiting(通过执行多个导航)来激活服务人员。服务人员收到了,但什么也没发生。它停留在“等待激活”状态。当我在Chrome中按skipWaiting时,它就工作了

我不知道出了什么问题。这是Chrome、workbox或其他产品的问题吗

最接近这个话题的是:

我使用Vue.js,但我不依赖服务工作者的pwa插件。我使用workbox网页包插件

我编辑了下面的示例代码,最小的代码可能没有很好地显示问题

在main.js中:

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为什么使用另一种模式吗?