Javascript 服务工作者正在缓存文件,但从未触发提取事件
我刚刚尝试在静态站点(在localhost chrome 47.0.2526.73(64位)上运行)上实现服务工作者来缓存一些JSON文件和其他资产。使用cache.addAll()我已将文件添加到缓存中,当我在chrome中打开“资源”选项卡并单击“缓存存储”时,所有文件都会列出 我遇到的问题是,我的服务人员在中被列为“已激活”和“正在运行”chrome://service-worker-internals 但是,我无法确定工作进程是否真的在拦截请求并提供缓存文件。我添加了事件监听器,即使我在ServiceWorkers开发工具实例中记录事件,它也不会到达断点:Javascript 服务工作者正在缓存文件,但从未触发提取事件,javascript,google-chrome,service-worker,progressive-web-apps,Javascript,Google Chrome,Service Worker,Progressive Web Apps,我刚刚尝试在静态站点(在localhost chrome 47.0.2526.73(64位)上运行)上实现服务工作者来缓存一些JSON文件和其他资产。使用cache.addAll()我已将文件添加到缓存中,当我在chrome中打开“资源”选项卡并单击“缓存存储”时,所有文件都会列出 我遇到的问题是,我的服务人员在中被列为“已激活”和“正在运行”chrome://service-worker-internals 但是,我无法确定工作进程是否真的在拦截请求并提供缓存文件。我添加了事件监听器,即使我
this.addEventListener('install', function(event) {
event.waitUntil(
caches.open('v1').then(function(cache) {
console.log(cache);
return cache.addAll([
'/json/0.json',
'/json/1.json',
'/json/3.json',
'/json/4.json',
'/json/5.json',
]);
})
);
});
this.addEventListener('fetch', function(event) {
console.log(event);
var response;
event.respondWith(caches.match(event.request).catch(function() {
return fetch(event.request);
}).then(function(r) {
response = r;
caches.open('v1').then(function(cache) {
cache.put(event.request, response);
});
return response.clone();
}).catch(function() {
}));
});
基本上,我完全按照HTML5 rocks service workers简介中的描述运行,但我非常确定我的资产不是从缓存中提供的。我注意到,在大小列的devtools的network选项卡中,通过指示“fromserviceworkers”,可以对服务人员提供的资产进行注释
似乎我的代码与示例没有什么不同,但出于某种原因,它从来没有遇到过fetch事件。我的代码要点:HTML5Rocks文章中的确切代码是
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// Cache hit - return response
if (response) {
return response;
}
// IMPORTANT: Clone the request. A request is a stream and
// can only be consumed once. Since we are consuming this
// once by cache and once by the browser for fetch, we need
// to clone the response
var fetchRequest = event.request.clone();
return fetch(fetchRequest).then(
function(response) {
// Check if we received a valid response
if(!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// IMPORTANT: Clone the response. A response is a stream
// and because we want the browser to consume the response
// as well as the cache consuming the response, we need
// to clone it so we have 2 stream.
var responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(function(cache) {
cache.put(event.request, responseToCache);
});
return response;
}
);
})
);
});
我能看到的最大的一点是,您没有从fetch中克隆
请求
,您需要克隆它,因为它被读取两次,一次是在用于访问网络时(在fetch
中)当被用作缓存的键时,如果您没有看到service worker中的标记,则您的页面尚未由service worker控制(您可以通过检查客户端页面中的navigator.serviceWorker.controller
进行检查)。页面的默认行为是在软件激活后下次访问时受到控制,因此您有两个选项:
- 注册后刷新页面
- 在安装和激活期间分别使用
和self.skipWaiting()
方法强制服务人员尽快控制客户端self.clients.claim()
self.onfetch = function (event) {
var req = event.request;
return event.respondWith(function cacheFirst() {
// Open your cache.
return self.caches.open('v1').then(function (cache) {
// Check if the request is in there.
return cache.match(req).then(function (res) {
// If not match, there is no rejection but an undefined response.
if (!res) {
// Go to network.
return fetch(req.clone()).then(function (res) {
// Put in cache and return the network response.
return cache.put(req, res.clone()).then(function () {
return res;
});
});
}
return res;
});
});
});
}
在看了你的要点和问题之后,我认为你的问题在于范围界定 根据我对service worker(至少是静态文件)的判断,service worker只有它所在目录的最大作用域。也就是说,它不能加载从其结构处或其上方(仅在其结构下方)提取的文件/请求/响应 例如,/js/service-worker.js将只能加载/js/{dirName}/中的文件 因此,如果您将服务工作者的位置更改为web项目的根目录,则应触发fetch事件,并从缓存加载资产 所以类似于/service-worker.js的东西应该能够访问/json目录,因为它比service-worker.js文件更深
这在这里的“注册服务人员”部分有进一步的解释 我为此挣扎了很长一段时间,我认为与此相关的文档严重缺乏。根据我的经验,有一个非常重要的区别: 服务工作者只能在其访问的URL范围之内或之上拦截获取事件 例如,我的sw.js文件位于
/static/sw.js
。当访问位于/
的我的站点根目录并试图截取/static/js/common.js
中js文件的获取事件时,获取事件没有被截取,即使我的服务人员的范围是/static/
,js文件在/static/js/
中
一旦我将sw.js文件移动到顶级作用域/sw.js
,获取事件都被截获。这是因为我使用浏览器/
访问的页面范围与我的sw.js文件/
的范围相同
请让我知道这是否为人们澄清了问题,或者如果我不正确 我在Django框架中使用sw.js时也遇到了同样的问题。
我找到了解决方案。你找到解决方案了吗?我认为@Stephen Archers的提示应该标记为正确。是的,你应该将@Stephen Archers的答案标记为正确。Stephen的答案应该标记为正确。我在将web-worker.js存储在子文件夹/assets/js/中时遇到了同样的问题。在存储文件并注册web worker时,它无法获取get请求。在我将它移动到这个域的根目录后,它工作得很好。服务人员能够访问它自己目录中的文件吗?i、 e
app/service worker.js
,它可以读取app/offline page.html
?@前缀是的,应该可以。如果serviceworker不在根目录中,我也会遇到同样的问题,serviceworker真的可以在子文件夹中找到吗?谢谢。也为我工作!我从未见过这样的实现使用返回self.caches.open('v1')。那么(函数(cache){你能给我这个方法的链接吗?这是比其他更好的解释。谢谢!@garviand:如果我使用“允许服务器工作者”头作为响应,而不是将我的文件移动到根目录,会发生什么?