8

我有一个服务人员。这是安装事件:

self.addEventListener('install', function (event) {
    console.log('Installing Service Worker ...', event);

    return self.skipWaiting()
    .then(() => caches.open(CACHE_STATIC_NAME))
    .then(function (cache) {
        return cache.addAll([
            './file1.html',
            './file2.html'
        ])
    })
});

出于某种原因,当我编辑 service worker 代码并更新 service worker 文件 URL 中的查询参数时,它会安装但不会激活(根据 Chrome DevTools)——即使我调用了self.skipWaiting().

奇怪的是,如果我进入控制台,进入服务人员的范围并输入self.skipWaiting()自己,它会立即激活。

几个小时以来,我一直在努力弄清楚发生了什么,我完全被难住了。我在这里缺少什么吗?

4

2 回答 2

8

旧的 SW 在它仍在运行任务时可能不会停止 - 例如,如果它有一个长时间运行的获取请求(例如服务器发送的事件/事件源或获取流;虽然我不认为 websockets 会导致这种情况,因为 SW 会忽略它们我认为)。

但是,我发现浏览器之间的行为有所不同。Chrome 似乎在现有任务运行时等待(因此 skipWaiting 将失败......),但 Safari 似乎终止了该任务并激活了新的 SW。

测试这是否导致您的问题的一个好方法是在您请求 skipWaiting 之后立即终止您的服务器(以终止网络连接)。(只是在开发工具中单击“离线”似乎并没有杀死所有正在运行的连接,例如 EventSources 保持运行。)

您可以让 SW 忽略某些路由(如下),或者您可以尝试强制终止请求(可能使用 AbortController)。

self.addEventListener('fetch', function(event) {
  const { method, url } = event.request;
  if(event.request.method !== "GET") return false;
  if(url === "https://example.com/poll") return false;

  event.respondWith(
    caches.match(match).then(function(response) {
      return response || fetch(event.request);
    })
  );
});

skipWaiting 的过程在此规范中:

https://w3c.github.io/ServiceWorker/#try-activate-algorithm

但是在激活新的 SW 之前,我发现浏览器是否应该等待任务或终止它们(或将它们转移到新的 SW?)不是很清楚;如前所述,目前浏览器之间的工作方式似乎有所不同......

于 2019-06-11T02:46:44.230 回答
0

我遇到过同样的问题。

我通过@ej.daly 给出的技巧验证了我的问题,我应该停止服务器,等待服务人员将在几分钟内激活。

之后,我在我的代码中应用了一个 hack:如果 WAITING 服务工作者在接下来的 3 秒内没有被激活,则重新加载窗口。

顺便说一句,我正在开发一个库,以便为我们公司的各种(常用)场景轻松安装服务人员。看看https://github.com/DreamworldSolutions/workbox-installer

于 2021-04-25T13:34:19.243 回答