我正在创建PWA,并且想在可用的更新服务程序可用时提示用户,但是无论我是否致电skipWaiting()
还是在开发控制台中手动按skipWaiting
,它都处于等待阶段
仅当我首先停止现有服务工作程序时,才会安装新的服务工作程序。
我也尝试通过在安装阶段直接调用self.skipWaiting()
来强制安装,但是我更新后的服务工作者仍然陷入等待阶段。
这是我的设置。
sw.js
// when installing hydrate caches and notify user that reload if required (if any)
self.addEventListener('install', async () => {
// self.skipWaiting();
await hydrateCache();
});
self.addEventListener('message', (message) => {
if (message.data === 'skipWaiting') {
debugger;
self.skipWaiting();
}
});
index.html
navigator.serviceWorker.register('sw.js')
.then(function (reg) {
reg.onupdatefound = function() {
var newServiceWorker = reg.installing;
if (reg.waiting && confirm('Updates are available, Would you like to reload?')) {
newServiceWorker.postMessage('skipWaiting');
}
newServiceWorker.onstatechange = function() {
// for some reason I am not getting waiting state update so I am prompting user
// when client gets installed phase update
if (newServiceWorker.state === 'installed') {
if (confirm('Updates are available, Would you like to reload?')) {
newServiceWorker.postMessage('skipWaiting');
}
}
}
}
navigator.serviceWorker.addEventListener('controllerchange', function() {
window.location.reload();
});
})
.catch(function (err) {
console.error('register err', err);
});
我希望每当我向服务工作者发送skipWaiting
消息时,它都应该替换现有的serviceWorker,我的代码会调用self.skipWaiting()
,但是在开发控制台中,我更新的服务工作者仍然停留在等待阶段,即使我手动按下skipWaiting
,它不会替换现有的服务人员。
更新:
因此,在修改代码后,我发现了一件有趣的事情,即使我调用了'fetch'
,我的skipWaiting()
事件处理程序中的某些东西仍阻止了我更新的服务工作者被激活。
此代码不会让新服务人员被激活
// intercept fetch requests and responds with cached file if they are available like CDN Files
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then((response) => {
if (response) {
console.log('Found ', event.request.url, ' in cache');
return response;
}
console.log('fetching', event.request.url, 'from internet');
return fetch(event.request);
})
.catch((err) => {
console.error('fetch error', err);
}),
);
});
如果我从'fetch'
偶数处理程序中删除了自定义代码,则当我致电skipWaiting()
时,我更新的服务工作程序将被激活。一旦我的工作人员拦截了一个请求,它将立即尝试从Internet上获取该请求,我基本上不会对'fetch'
处理程序进行任何操作。
self.addEventListener('fetch', (event) => {
return fetch(event.request);
});