ServiceWorkerGlobalScope:fetch 事件
注意:此功能仅在Service Workers中可用。
当主应用程序线程发出网络请求时,ServiceWorkerGlobalScope
接口的fetch
事件将在服务工作者的全局作用域中触发。它使服务工作者能够拦截网络请求并发送自定义响应(例如,来自本地缓存)。
此事件不可取消,也不冒泡。
语法
在诸如addEventListener()
之类的事件中使用事件名称,或设置事件处理程序属性。
addEventListener("fetch", (event) => {});
onfetch = (event) => {};
描述
当主应用程序线程发出网络请求时,fetch
事件将在服务工作者的全局作用域中触发。这不仅包括来自主线程的显式fetch()
调用,还包括浏览器在页面导航后为加载页面和子资源(如 JavaScript、CSS 和图像)而发出的隐式网络请求。
事件处理程序将传递一个FetchEvent
对象,该对象提供对请求(作为Request
实例)的访问。
FetchEvent
还提供了一个respondWith()
方法,该方法以Response
(或解析为Response
的Promise
)作为参数。这使服务工作者事件处理程序能够提供返回到主线程中请求的响应。
例如,服务工作者可以返回
- 从
Cache
接口检索的本地缓存响应。 - 服务工作者使用
Response.json()
或Response()
构造函数等方法合成的响应。 - 使用
Response.error()
方法的网络错误。这将导致fetch()
调用被拒绝。
对于给定的请求,只能调用一次respondWith()
方法。如果添加了多个fetch
事件侦听器,则将按照它们注册的顺序调用它们,直到其中一个调用respondWith()
。
必须同步调用respondWith()
方法:也就是说,您不能在then
处理程序中调用它。
通常,fetch
事件处理程序将根据请求的特性(例如其 URL)执行不同的策略
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()
,则用户代理会自动发出原始网络请求。例如,在上面的代码中,所有与pattern1
或pattern2
不匹配的请求都将像服务工作者不存在一样发出。
事件类型
示例
回退到网络的缓存
此fetch
事件处理程序首先尝试在缓存中查找响应。如果找到响应,则返回缓存的响应。否则,它将尝试从网络获取资源。
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"
,则处理程序仅在缓存中查找,如果未找到响应则返回错误。所有其他请求都将通过网络进行。
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 的浏览器中加载。