Service Worker缓存不稳定问题排查求助
Service Worker Fetch Event Error: Non-Response Object Passed to
respondWith() 我来帮你排查这个问题——你遇到的错误核心原因是你的Service Worker在fetch事件的respondWith()里返回了非Response对象,具体来说是当网络请求失败且缓存中没有匹配资源时,你返回了undefined,而浏览器要求respondWith()必须接收一个Response实例或者能解析为Response的Promise。
问题代码分析
看你fetch事件处理的最后一段:
.catch(err => caches.match(e.request).then(res => res))
当网络请求失败进入catch后,caches.match(e.request)如果找不到对应的缓存资源,会resolve为undefined。你直接把这个undefined返回给respondWith(),这就触发了浏览器的错误提示:“an object that was not a Response was passed to respondWith()”。
修复方案
你需要确保无论什么情况,respondWith()最终拿到的都是合法的Response对象。修改catch逻辑,当缓存也找不到资源时,返回一个自定义的离线响应:
self.addEventListener('fetch', function (e) { console.log("Service Worker: Fetch") e.respondWith( fetch(e.request) .then(res => { // Make copy/clone of response const responseClone = res.clone() // Open Cache caches .open(cacheName) .then(cache => { // Add response to cache cache.put(e.request, responseClone) }) return response }).catch(err => caches.match(e.request).then(res => { // 如果缓存有资源就返回,否则返回自定义离线响应 return res || new Response('<h1>Offline: This resource isn\'t cached</h1>', { headers: { 'Content-Type': 'text/html' } }) }) ) ) })
更健壮的缓存策略(可选)
如果想优化用户体验,推荐使用“Cache First, Update in Background”的策略——优先返回缓存资源,同时后台用网络请求更新缓存,这样离线时用户也能看到内容:
self.addEventListener('fetch', function (e) { console.log("Service Worker: Fetch"); e.respondWith( caches.match(e.request) .then(cachedRes => { // 有缓存直接返回,后台悄悄更新缓存 if (cachedRes) { fetch(e.request).then(networkRes => { caches.open(cacheName).then(cache => { cache.put(e.request, networkRes.clone()); }); }); return cachedRes; } // 无缓存则走网络,成功后缓存结果 return fetch(e.request) .then(networkRes => { const responseClone = networkRes.clone(); caches.open(cacheName).then(cache => { cache.put(e.request, responseClone); }); return networkRes; }) .catch(err => { // 网络和缓存都失败,返回统一离线提示 return new Response('<h1>Offline Mode: No cached content available</h1>', { headers: { 'Content-Type': 'text/html' } }); }); }) ); })
额外提示
- 测试时可以在Chrome DevTools的Application > Cache Storage里查看缓存的资源,确认哪些资源被正确缓存
- 每次修改Service Worker后,记得更新
cacheName(比如改成v3),这样激活时会自动清理旧缓存
内容的提问来源于stack exchange,提问作者Chud37
相关产品推荐
相关产品推荐

