Serviceworker: Provide an easier way to listen for waiting/activated/redundant Service Workers

Created on 14 Dec 2017  路  6Comments  路  Source: w3c/ServiceWorker

Breaking off from #1222.

ServiceWorker.state has five states: installing, installed (waiting), activating, activated, and redundant.

Today, client-side code can listen for installing SWs with ServiceWorkerRegistration.onupdatefound; activating can be tracked with navigator.serviceWorker.oncontrollerchange.

The other three states are annoying to listen for.

function listenForStateChanges(reg, callback) {
  if (reg.installing) reg.installing.addEventListener('statechange', callback);
  if (reg.waiting) reg.waiting.addEventListener('statechange', callback);
  reg.addEventListener('updatefound', function() {
    reg.installing.addEventListener('statechange', callback);
  });
}

That's too bad, because lots of users want to track the installed state so they can show a refresh banner. Furthermore, some users apparently want to track redundant SWs for error handling. And it turns out that refreshing the page as the page is activating is slightly too soon; you should wait for the activated event, to avoid a minor performance bug.

In #1222 we observed that awaiting these states would be way easier if statechange bubbled up to the registration, so users who wanted to track the redundant and activated states would just do this:

reg.addEventListener('statechange', callback);

Most helpful comment

A promise doesn't really work in this case, as many service workers can pass through the waiting phase during the life of a page.

All 6 comments

Alerting users of a waiting service worker might look like this:

Combined with #1016, that means that showing a "please refresh" banner could work like this:

function alertUser(reg) {
  // don't use confirm in production; this is just an example
  if (confirm('Refresh now?')) reg.waiting.skipWaiting();
}

if (reg.waiting) alertUser(reg);
reg.addEventListener('statechange', function(e) {
  if (e.target.state === 'installed') {
    alertUser(reg);
  } else if (e.target.state === 'activated') {
    window.location.reload();
  }
});

@dfabulich I like your suggestion. I can't believe nobody has been assigned to fix this!

A promise doesn't really work in this case, as many service workers can pass through the waiting phase during the life of a page.

To be clear, this issue #1247 doesn't involve Promises; it calls for the statechange event to bubble up to the registration. Issue #1222 recommends a Promise; I'll copy and paste your comment there.

In fact, this issue was originally @jakearchibald's idea, in a comment on #1222.

As far as I can tell, nobody has had anything bad to say about it. I might have preferred #1222, but since that approach seems to be dead in the water, this is still a big improvement over the status quo.

+1 for @dfabulich prolyfil idea. 3 years old and still needed IMO.

Was this page helpful?
0 / 5 - 0 ratings