检查ServiceWorker是否处于等待状态

To check if ServiceWorker is in waiting state

我正在尝试了解 Service Worker API,并且我知道有关注册 Service Worker 的细节。

如 API 文档中所述,如果发现服务工作者更新,服务工作者将被注册并添加到队列中。此 SW 接管页面当且仅当页面关闭并打开 again.That 是,A window 关闭并再次打开。

现在,这有一些缺点:

  1. 用户可能看到的是以前的版本,该版本可能存在非常严重的语法错误或其他任何错误。

  2. 需要以某种方式通知用户内容已更改,并且需要重新提交。

我知道如何告诉 SW.jsskipWaiting() 并接管。我也知道如何向 SW.js 发送消息,告诉它用户想要自动刷新。

但是,我不知道的是如何知道一个新的SW是否真的处于等待状态。

我用过这个:

navigator.serviceWorker.ready.then((a) => {
        console.log("Response, ", a);
        if (a.waiting !== null && a.waiting.state === "installed") {
            console.log("okay");
        }

    });

然而,它通常returns等待状态为null。(可能是因为当请求被触发时软件仍在安装。)

我如何在客户端页面上知道等待的 service worker 可用?

这里有一些代码可以检测并允许您在有新的或更新的 service worker 注册时处理各种状态。

请注意,日志消息假定 skipWaiting() 在 Service Worker 安装期间未被调用;如果它被调用,那么不必关闭所有选项卡来激活新的 service worker,它会自动激活。

if ('serviceWorker' in navigator) {
  window.addEventListener('load', async function() {
    const registration = await navigator.serviceWorker.register('/service-worker.js');
    if (registration.waiting && registration.active) {
      // The page has been loaded when there's already a waiting and active SW.
      // This would happen if skipWaiting() isn't being called, and there are
      // still old tabs open.
      console.log('Please close all tabs to get updates.');
    } else {
      // updatefound is also fired for the very first install. ¯\_(ツ)_/¯
      registration.addEventListener('updatefound', () => {
        registration.installing.addEventListener('statechange', () => {
          if (event.target.state === 'installed') {
            if (registration.active) {
              // If there's already an active SW, and skipWaiting() is not
              // called in the SW, then the user needs to close all their
              // tabs before they'll get updates.
              console.log('Please close all tabs to get updates.');
            } else {
              // Otherwise, this newly installed SW will soon become the
              // active SW. Rather than explicitly wait for that to happen,
              // just show the initial "content is cached" message.
              console.log('Content is cached for the first time!');
            }
          }
        });
      });
    }
  });
}