ServiceWorker:javascript触发的请求没有FetchEvent?
我使用的是Chrome stable 46 我有一个非常基本的网站。一个按钮。点击ServiceWorker:javascript触发的请求没有FetchEvent?,javascript,asp.net-web-api,fetch,service-worker,fetch-api,Javascript,Asp.net Web Api,Fetch,Service Worker,Fetch Api,我使用的是Chrome stable 46 我有一个非常基本的网站。一个按钮。点击fetch('a'),一个标签打开b。URLa和b都不存在,我打算在服务人员中捕获它们,然后返回一个新响应() 如果我单击获取a的按钮,则服务人员不参与,我得到一个404错误。 但是,如果我单击指向b的链接,服务人员将获取并返回响应 问题:为什么服务人员没有为fetch('a')请求获取任何FetchEvent 请参阅下面的文件 HTML sw.js 第一次加载页面时,不会调用服务人员的fetch事件处理程序,因为
fetch('a')
,一个
标签打开b
。URLa
和b
都不存在,我打算在服务人员中捕获它们,然后返回一个新响应()
如果我单击获取a
的按钮,则服务人员不参与,我得到一个404错误。
但是,如果我单击指向b
的链接,服务人员将获取并返回响应
问题:为什么服务人员没有为fetch('a')
请求获取任何FetchEvent
请参阅下面的文件
HTML
sw.js
第一次加载页面时,不会调用服务人员的fetch
事件处理程序,因为服务人员尚未“声明”页面,这意味着它不在服务人员的控制之下。默认情况下,第一次访问注册服务人员的站点时,服务人员的安装
(以及可能的激活
)事件处理程序将运行,但是获取
在服务人员取得控制权之前不会被触发。下次导航到服务工作者作用域下的页面时,或者重新加载当前页面时,会发生这种情况
您可以覆盖此默认行为,并让服务人员在初始导航期间通过调用self.clients.claim()
在activate
事件处理程序中进行控制
我还想指出,示例中的fetch
事件处理程序存在一些问题。如果您一直计划返回新的响应
对象,则没有理由调用caches.match(request)
。更重要的是,您需要对event.request.url
值进行某种检查,并且只返回新的响应
,前提是它与您的一个“特殊”url相匹配,在您的情况下是a
和b
。按照现在的实现方式,您的fetch
处理程序将无条件地返回虚拟响应
,即使它是对主页(index.html
)的后续请求。那大概不是你想要的
我放了一个修改服务人员代码的命令,以完成我认为您正在尝试的任务。你可以试试感谢罗吉特。以下是经过修改的服务人员代码:
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'));
}
});
为什么你有一个包含async和defer的脚本?@DanielHerr belt and braces。这个问题对我来说太神秘了,我完全忘记了声明只适用于进入新页面,而不适用于获取请求!谢谢你解除我的好奇心@Jeff您使用self.addEventListener
而不是self.on
是否有一个原因?相当于。使用aEL意味着我们可以注册多个回调,而不是通过onXYZ获得的单个回调。这是特别针对fetch的import,因为您可能会以这样的方式构造代码:您有几个回调,每个回调都有机会通过reapondWith()处理事件。
navigator.serviceWorker.register('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');
})
);
};
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'));
}
});