ServiceWorkerGlobalScope:fetch 事件

安全上下文:此功能仅在安全上下文(HTTPS)中可用,在某些或所有支持的浏览器中。

注意:此功能仅在Service Workers中可用。

当主应用程序线程发出网络请求时,ServiceWorkerGlobalScope接口的fetch事件将在服务工作者的全局作用域中触发。它使服务工作者能够拦截网络请求并发送自定义响应(例如,来自本地缓存)。

此事件不可取消,也不冒泡。

语法

在诸如addEventListener()之类的事件中使用事件名称,或设置事件处理程序属性。

js
addEventListener("fetch", (event) => {});

onfetch = (event) => {};

描述

当主应用程序线程发出网络请求时,fetch事件将在服务工作者的全局作用域中触发。这不仅包括来自主线程的显式fetch()调用,还包括浏览器在页面导航后为加载页面和子资源(如 JavaScript、CSS 和图像)而发出的隐式网络请求。

事件处理程序将传递一个FetchEvent对象,该对象提供对请求(作为Request实例)的访问。

FetchEvent还提供了一个respondWith()方法,该方法以Response(或解析为ResponsePromise)作为参数。这使服务工作者事件处理程序能够提供返回到主线程中请求的响应。

例如,服务工作者可以返回

对于给定的请求,只能调用一次respondWith()方法。如果添加了多个fetch事件侦听器,则将按照它们注册的顺序调用它们,直到其中一个调用respondWith()

必须同步调用respondWith()方法:也就是说,您不能在then处理程序中调用它。

通常,fetch事件处理程序将根据请求的特性(例如其 URL)执行不同的策略

js
function strategy1() {
  return fetch("picnic.jpg");
}

function strategy2() {
  return Response.error();
}

const pattern1 = /^\/salamander/;
const pattern2 = /^\/lizard/;

self.addEventListener("fetch", (event) => {
  const url = new URL(event.request.url);
  if (pattern1.test(url.pathname)) {
    event.respondWith(strategy1());
  } else if (pattern2.test(url.pathname)) {
    event.respondWith(strategy2());
  }
});

如果在处理程序中未调用respondWith(),则用户代理会自动发出原始网络请求。例如,在上面的代码中,所有与pattern1pattern2不匹配的请求都将像服务工作者不存在一样发出。

事件类型

示例

回退到网络的缓存

fetch事件处理程序首先尝试在缓存中查找响应。如果找到响应,则返回缓存的响应。否则,它将尝试从网络获取资源。

js
async function cacheThenNetwork(request) {
  const cachedResponse = await caches.match(request);
  if (cachedResponse) {
    console.log("Found response in cache:", cachedResponse);
    return cachedResponse;
  }
  console.log("Falling back to network");
  return fetch(request);
}

self.addEventListener("fetch", (event) => {
  console.log(`Handling fetch event for ${event.request.url}`);
  event.respondWith(cacheThenNetwork(event.request));
});

仅缓存

fetch事件处理程序对脚本和样式表实施“仅缓存”策略。如果请求的destination属性为"script""style",则处理程序仅在缓存中查找,如果未找到响应则返回错误。所有其他请求都将通过网络进行。

js
async function cacheOnly(request) {
  const cachedResponse = await caches.match(request);
  if (cachedResponse) {
    console.log("Found response in cache:", cachedResponse);
    return cachedResponse;
  }
  return Response.error();
}

self.addEventListener("fetch", (event) => {
  if (
    event.request.destination === "script" ||
    event.request.destination === "style"
  ) {
    event.respondWith(cacheOnly(event.request));
  }
});

规范

规范
Service Workers
# dom-serviceworkerglobalscope-onfetch

浏览器兼容性

BCD 表格仅在启用 JavaScript 的浏览器中加载。

另请参阅