哪个 service worker 事件表明它已经控制了页面,并将拦截网络流量?

Which service worker event indicates it has controlled the page, and will intercept web traffic?

在我的网络应用中,一些网络请求必须被服务工作者拦截和修改,否则请求将失败。这对于新用户的首次访问尤为重要。我使用 clientsClaim() 来确保这一点。

因为我需要在发出请求之前确保 service worker 准备就绪,所以我尝试等待 navigator.serviceWorker.ready:

await navigator.serviceWorker.ready;
fetch(myRequest);

但是,我发现它没有按预期工作。第一次访问的第一个请求不会被拦截。所以我试着增加一些等待时间:

await navigator.serviceWorker.ready;
await twoSeconds();
fetch(myRequest);

这可行,但它会损害用户体验,因为它会延迟第一个有意义的 UI。另一方面,我也不能确定 2 秒对每台计算机来说是否足够长。

一旦 sw 准备好拦截流量,有什么事件可以告诉我?这只是第一次访问时的问题,但理想情况下,事件会在每次重新加载时触发,因为如果我在每次访问时都简单地等待相同的事情,代码会更容易编写。

我认为您正在寻找一种承诺,当当前页面处于服务工作者的控制之下时,您可以使用它来发出信号。

这可以通过

实现
await new Promise(r => {
  if (navigator.serviceWorker.controller) return r();
  navigator.serviceWorker.addEventListener('controllerchange', e => r());
});

// At this point, the page will be controlled by a service worker.

此代码改编自 GitHub discussion,其中包含更多上下文。

一般来说,设计一个只有在服务工作者控制下才能工作的页面并不是很好,因为服务工作者旨在逐步增强,而不是核心要求。但是如果你有那个用例,上面的代码会有所帮助。