[ServiceWorker] Have clients.claim() wait until controllers have changed before resolving (#799)

In the following sample code ([live version](https://rawgit.com/jeffposnick/66dffeb92dfdd20d9aac/raw/a7f3ce696c56e496e9736f05869969926fbdecc3/index.html)), I ended up making a wrong assumption that might catch other developers by surprise:

Excerpt from `index.html`:
```js
navigator.serviceWorker.register('sw.js');
navigator.serviceWorker.ready.then(() => {
  // I thought the page would be controlled at this point, thanks to clients.claim()
  console.log('.ready resolved, and navigator.serviceWorker.controller is', navigator.serviceWorker.controller);
  navigator.serviceWorker.addEventListener('controllerchange', () => {
    console.log('Okay, now things are under control. navigator.serviceWorker.controller is', navigator.serviceWorker.controller);
  });
});
```

`sw.js`:
```js
self.addEventListener('install', event => event.waitUntil(self.skipWaiting()));
self.addEventListener('activate', event => event.waitUntil(self.clients.claim()));
```

The assumption I had was that, by virtue of waiting on `clients.claim()` inside the SW's `activate` handler, the page will end up being controlled once `.ready` resolves. However, that's apparently a bad assumption, because the [spec for `clients.claim()`](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#clients-claim) states that the promise doesn't wait before resolving.

Is there any appetite for changing the behavior of `clients.claim()` so that the promise it returned waits until all the controller changes have taken place before it resolves? That would allow `event.waitUntil(self.clients.claim())` within an `activate` handler to have the effect that I assumed it had, and it would by extension make the `.ready` promise more useful.

---
Reply to this email directly or view it on GitHub:
https://github.com/slightlyoff/ServiceWorker/issues/799

Received on Thursday, 10 December 2015 22:22:04 UTC