I have a simple service worker with button update when new service worker is in queue. After update I want to make page refresh on controllerchange but nothing happens. All in all service worker is updated live but following that course () they try to add that refresh for some reason.
In js:
const updateButton = document.querySelector('.js-update-btn')
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js')
.then(function (reg) {
if (!navigator.serviceWorker.controller) {
return
}
if (reg.waiting) {
updateReady(reg.waiting)
return
}
if (reg.installing) {
trackInstalling(reg.installing)
return
}
reg.addEventListener('updatefound', function () {
trackInstalling(reg.installing)
})
})
var refreshing
navigator.serviceWorker.addEventListener('controllerchange', function () {
if (refreshing) return
window.location.reload()
refreshing = true
})
}
function updateReady (worker) {
updateButton.disabled = false
updateButton.addEventListener('click', function () {
updateButton.disabled = true
worker.postMessage({action: 'skipWaiting'})
})
}
function trackInstalling (worker) {
worker.addEventListener('statechange', function () {
if (worker.state == 'installed') {
updateReady(worker)
}
})
}
In sw.js:
self.addEventListener('message', function (event) {
if (event.data.action == 'skipWaiting') {
self.skipWaiting()
}
})
I have a simple service worker with button update when new service worker is in queue. After update I want to make page refresh on controllerchange but nothing happens. All in all service worker is updated live but following that course (https://www.udacity.com/course/offline-web-applications--ud899) they try to add that refresh for some reason.
In js:
const updateButton = document.querySelector('.js-update-btn')
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js')
.then(function (reg) {
if (!navigator.serviceWorker.controller) {
return
}
if (reg.waiting) {
updateReady(reg.waiting)
return
}
if (reg.installing) {
trackInstalling(reg.installing)
return
}
reg.addEventListener('updatefound', function () {
trackInstalling(reg.installing)
})
})
var refreshing
navigator.serviceWorker.addEventListener('controllerchange', function () {
if (refreshing) return
window.location.reload()
refreshing = true
})
}
function updateReady (worker) {
updateButton.disabled = false
updateButton.addEventListener('click', function () {
updateButton.disabled = true
worker.postMessage({action: 'skipWaiting'})
})
}
function trackInstalling (worker) {
worker.addEventListener('statechange', function () {
if (worker.state == 'installed') {
updateReady(worker)
}
})
}
In sw.js:
self.addEventListener('message', function (event) {
if (event.data.action == 'skipWaiting') {
self.skipWaiting()
}
})
Share
Improve this question
edited Jan 27, 2017 at 14:39
Jeff Posnick
56.1k14 gold badges147 silver badges174 bronze badges
asked Jan 27, 2017 at 9:48
KrystusKrystus
3153 gold badges4 silver badges14 bronze badges
2 Answers
Reset to default 11I would recommend following the example from the sw-precache
demo code.
Here's a very concise, modified version of that example that will force a page reload when there's an update to an already installed service worker. (I'd argue that it might be more user-friendly to display a message on the page asking the user to reload manually, though, so that you don't end up interrupting whatever they were doing on the page.)
navigator.serviceWorker.register('/service-worker.js').then(reg => {
reg.onupdatefound = () => {
const installingWorker = reg.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed' &&
navigator.serviceWorker.controller) {
// Preferably, display a message asking the user to reload...
location.reload();
}
};
};
});
After many attempts I come with something like that.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js')
.then(function (reg) {
if (!navigator.serviceWorker.controller) {
return
}
reg.addEventListener('updatefound', function () {
const newWorker = reg.installing
newWorker.state
var refreshing
newWorker.addEventListener('statechange', () => {
if (newWorker.state == 'activated') {
if (refreshing) return
window.location.reload()
refreshing = true
}
})
trackInstalling(reg.installing)
})
})
}
It's working. Is there any flaws of that code?