我已经在教程的帮助下写了一个服务工作者:
var CACHE = 'cache-and-update';
self.addEventListener('install', function (evt) {
console.log('The service worker is being installed.');
evt.waitUntil(precache());
});
self.addEventListener('fetch', function (evt) {
evt.respondWith(fromCache(evt.request));
evt.waitUntil(update(evt.request));
});
function precache() {
return caches.open(CACHE).then(function (cache) {
return cache.addAll([
// Nothing.
]);
});
}
function fromCache(request) {
return caches.open(CACHE).then(function (cache) {
return cache.match(request).then(function (matching) {
return matching || Promise.reject('no-match');
});
});
}
function update(request) {
return caches.open(CACHE).then(function (cache) {
return fetch(request).then(function (response) {
return cache.put(request, response);
});
});
}
始终总是先从缓存中提供服务,然后获取所有文件,并在页面重新加载时进行更新。
在我的服务器上的每个HTML文件中,服务工作者都是这样注册的:
<script>
navigator.serviceWorker.register('https://www.example.com/sw.js', {
scope: '../'
});
</script>
现在的问题是,当我转到尚未缓存的页面时,它首先向我显示默认的Chrome ERR_FAILED
错误(以及“不匹配”的承诺被拒绝)。
然后,无论如何,sw都会获取它,同时向客户端显示错误页面,并在重新加载后再次起作用(因为它是从缓存中提供的)。
为什么会发生这种情况?当没有可用的缓存版本时,如何使服务工作者从服务器加载页面?
答案 0 :(得分:1)
您在这里错误地获取了监听器,
如果您在缓存中找不到文件,则拒绝诺言,您应该先获取文件然后缓存它,而不是返回Promise.reject('no-match')
,并且在这种情况下不需要evt.waitUntil
这是服务中的工作人员的完整摘要。如果请求与缓存中的任何内容都不匹配,我们将从网络中获取该请求,将其发送到页面,然后同时将其添加到缓存中。
let cacheName = 'cache-v1';
self.addEventListener('install', (e) => {
let cache = caches.open(cacheName).then((c) => {
c.addAll([
// nothing
]);
});
e.waitUntil(cache);
});
self.addEventListener('fetch', function (event) {
event.respondWith(
caches.open(cacheName).then(function (cache) {
return cache.match(event.request).then(function (response) {
return response || fetch(event.request).then(function (response) {
cache.put(event.request, response.clone());
return response;
});
});
})
);
});