Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

self.skipWaiting() not working in Service Worker

I have a service worker. Here's the install event:

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'
        ])
    })
});

For some reason, when I edit the service worker code and update the query parameter in the service worker file URL, it installs but does not activate (according to Chrome DevTools) — even though I've called self.skipWaiting().

Oddly if I go into the console, go to the scope of the service worker and type self.skipWaiting() myself, it activates immediately.

I've been trying to work out what's going on for many hours now, and I'm completely stumped. Is there something I'm missing here?

like image 926
Ethan Avatar asked Feb 11 '19 10:02

Ethan


Video Answer


1 Answers

The old SW might not stop while it's still running tasks - for example if it had a long running fetch request (e.g server sent events / event source, or fetch streams; although I don't think websockets can cause this as SW will ignore them I think).

I find the behaviour to be different between browers however. Chrome seems to wait while the existing task is running (so skipWaiting will fail...), but Safari seems to kill the task and activate the new SW.

A good way to test if this is causing your issue would be to kill your server just after you request the skipWaiting (to kill the network connections). (Just clicking "Offline" in Dev Tools doesn't seem to kill all running connections, for example EventSources stay running.)

You can have the SW ignore certain routes (below), or you could try and force the requests to terminate (maybe using 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);
    })
  );
});

The process for skipWaiting is in this spec:

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

But I don't find it very clear about whether the browser should wait for tasks or terminate them (or transfer them to the new SW?), before activating the new SW; and as mentioned, it seems to work differently between browsers at the moment...

like image 164
ej.daly Avatar answered Oct 22 '22 04:10

ej.daly