ServiceWorker:javascript触发的请求没有FetchEvent?

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事件处理程序,因为

我使用的是Chrome stable 46

我有一个非常基本的网站。一个按钮。点击
fetch('a')
,一个
标签打开
b
。URL
a
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'));
  }
});