serviceworker 拦截 fetch 请求需监听 fetch 事件并调用 event.respondwith() 返回响应;注册须同源、https,激活后生效;仅拦截同源请求,不可读 opaque 响应;注意缓存策略与 clone 前校验 bodyused。

在 ServiceWorker 中拦截并处理 fetch 请求,核心是监听全局的 fetch 事件,并在事件回调中调用 event.respondWith() 返回自定义响应。这不同于页面中的 fetch 调用,ServiceWorker 是通过事件机制“劫持”所有经过它的网络请求(包括页面 fetch、XMLHttpRequest、资源加载等)。
注册并激活 ServiceWorker
确保 ServiceWorker 已正确注册且处于 activated 状态,否则 fetch 事件不会触发:
- 注册脚本需与页面同源,通常在主 JS 中调用
navigator.serviceWorker.register('/sw.js') -
sw.js文件必须是 HTTPS(或localhost),且响应状态码为 200 - 首次注册后需刷新页面,或调用
skipWaiting()+clients.claim()加速激活
监听 fetch 事件并返回响应
在 sw.js 中监听 fetch 事件,用 event.respondWith() 拦截请求:
清晰、专业的暖通空调服务客户教育手册,包含图片、常见问题及可操作的下一步,帮助客户理解并提升参与度。
-
event.request是只读的Request对象,可读取 URL、method、headers 等 - 必须调用
event.respondWith(promise),否则请求会失败(报TypeError: Failed to fetch) - 返回值可以是缓存响应(
cache.match())、网络响应(fetch(event.request))、或全新构造的Response
示例:优先返回缓存,缓存未命中则走网络
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
// 可选:跳过某些请求(如第三方资源、导航请求)
if (url.origin !== location.origin || event.request.destination === 'document') {
return;
}
event.respondWith(
caches.match(event.request).then(cached => {
if (cached) return cached;
return fetch(event.request).then(response => {
// 可选:将响应存入缓存(注意非 GET 请求通常不缓存)
if (response.status === 200 && event.request.method === 'GET') {
const cache = await caches.open('my-cache');
cache.put(event.request, response.clone());
}
return response;
});
})
);
});
注意跨域与请求限制
ServiceWorker 的 fetch 拦截有明确边界:
- 仅拦截同源请求(
event.request.url与 SW 脚本同源),除非使用navigationPreload或importScripts加载跨域资源(但不能直接拦截) - 无法拦截
opaque响应(如跨域无 CORS 的图片/脚本),其response.type为'opaque',且 headers/body 不可读 - 导航请求(
destination === 'document')默认不被缓存,需显式处理(例如用navigationPreload或返回 fallback HTML)
调试与常见陷阱
开发时建议开启 Chrome 的 “Update on reload” 和 “Bypass for network”,并在 Application → Service Workers 面板中检查状态:
- 忘记调用
event.respondWith()→ 请求卡住或失败 - 在
respondWith()中抛出未捕获错误 → 请求失败,控制台显示 unhandled rejection - 对 POST/PUT 等请求直接缓存响应 → 可能导致数据不一致,应谨慎判断是否缓存
- 使用
response.clone()前未确认response.bodyUsed === false→ 报错 “Failed to execute 'clone' on 'Response': Response body is already used”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










