我正在使用Chrome stable 46。
我有一个非常基本的网站。只需一个按钮,即可点击fetch('a')
和一个<a>
标记即可打开b
。网址a
和b
都不存在,我打算在服务工作者中捕获它们,只返回new Response()
。
如果我点击提取a
的按钮,服务工作者不参与,我收到404错误。
但是,如果我点击转到b
的链接,服务工作人员就会获取并返回响应。
问题:为什么服务工作者没有获得fetch('a')
请求的任何FetchEvent?
请参阅以下文件
HTML
<html>
<body>
<p><button onclick="fetch('a');">fetch a</button></p>
<p><a href="b">go to b</a></p>
<script src="js.js" defer></script>
</body>
</html>
js.js
navigator.serviceWorker.register('sw.js');
sw.js
self.onfetch = function(event) {
var request = event.request;
event.respondWith(
caches.match(request).then(function(response) {
return new Response('here is your onfetch response');
})
);
};
答案 0 :(得分:7)
首次加载页面时,服务工作者的fetch
事件处理程序不会被调用,因为服务工作者尚未声明&#34;&#34;页面,这意味着它不受服务工作者的控制。默认情况下,当您第一次访问注册服务工作者的站点时,服务工作者的install
(以及可能activate
)事件处理程序将运行,但fetch
赢了&# 39;在服务人员控制之前触发。下次导航到服务工作者范围下的页面时,或者重新加载当前页面时,会发生这种情况。
您可以覆盖此默认行为,并在初始导航期间通过调用self.clients.claim()
事件处理程序中的activate
来控制服务工作者。
我还想指出示例中的fetch
事件处理程序存在一些问题 - 如果您一直计划返回一个问题,则没有理由致电caches.match(request)
新的Response
对象。更重要的是,您需要对event.request.url
值进行某种检查,只有当它与您的某个&#34;特殊&#34;匹配时,才会返回新的Response
。网址,在您的情况下为a
和b
。现在实施的方式,您的fetch
处理程序将无条件地返回虚拟Response
,即使它是对您的主页(index.html
)的后续请求。这大概不是你想要的。
我添加了gist together来修改您的服务工作者代码,以完成我相信您正在尝试的内容。感谢RawGit,您可以尝试live version。对于后代,这里是修改过的服务工作者代码:
self.addEventListener('install', event => {
// Bypass the waiting lifecycle stage,
// just in case there's an older version of this SW registration.
event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', event => {
// Take control of all pages under this SW's scope immediately,
// instead of waiting for reload/navigation.
event.waitUntil(self.clients.claim());
});
self.addEventListener('fetch', event => {
// In a real app, you'd use a more sophisticated URL check.
if (event.request.url.match(/a|b$/)) {
event.respondWith(new Response('here is your onfetch response'));
}
});