ServiceWorkerContainer.ready resolves to an active ServiceWorkerRegistration, but if there are multiple service workers in play (e.g. service workers from previous page loads, multiple registrations within the same page) there are multiple service workers it could resolve to. How can I make sure that a particular service worker is handling network events when a chunk of code is executed?
That is, how can I write a function registerReady(scriptURL, options)
that can be used as follows:
registerReady("foo.js").then(function (r) {
// "foo.js" is active and r.active === navigator.serviceWorker.controller
fetch("/"); // uses foo.js's "fetch" handler
});
registerReady("bar.js").then(function (r) {
// "bar.js" is active and r.active === navigator.serviceWorker.controller
fetch("/"); // use bar.js's "fetch" handler
});
First, notice there can be only one active service worker per scope and your client page can be controlled by at most one and only one service worker. So, when ready resolves, you know for sure the service worker controlling your page is active.
To know if an arbitrary sw is active you can register it and check the queue of service workers in the registration and listen for changes in their state. For instance:
function registerReady(swScript, options) {
return navigator.serviceWorker.register(swScript, options)
.then(reg => {
// If there is an active worker and nothing incoming, we are done.
var incomingSw = reg.installing || reg.waiting;
if (reg.active && !incomingSw) {
return Promise.resolve();
}
// If not, wait for the newest service worker to become activated.
return new Promise(fulfill => {
incomingSw.onstatechange = evt => {
if (evt.target.state === 'activated') {
incomingSw.onstatechange = null;
return fulfill();
}
};
});
})
}
Hope it makes sense to you.