PWA中拦截fetch请求时如何正确返回缓存数据?
在开发PWA时,我尝试用Service Worker拦截fetch请求,想在网络错误时返回缓存数据。但发现当网络断开时,某些请求返回了504而不是缓存内容,这是为什么?
我的service worker代码类似这样:
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then(cacheRes => {
return cacheRes || fetch(event.request);
})
);
});
测试时发现,当第二次请求且断开网络,明明缓存存在却还是报错。难道是fetch顺序有问题?或者需要手动处理网络状态?
fetch抛出异常后没有捕获。我之前也踩过这坑,改一下代码逻辑就行。简单说就是加个
.catch,网络挂了就强制走缓存。别忘了测试各种断网场景,不然还是会出幺蛾子。我的血泪教训是,在 PWA 的 Service Worker 里,处理 fetch 请求一定要有兜底逻辑。具体来说,你需要捕获 fetch 的异常,并在捕获到异常时再次尝试从缓存中获取数据。下面是改好的代码:
这里的关键点有两个:第一,你要用 catch 捕获 fetch 抛出的异常;第二,catch 里面再次调用 caches.match,这样即使网络断开了,也有机会从缓存里拿数据。
另外提醒一下,caches.match 是按请求 URL 和方法匹配的,所以如果你的缓存策略有问题,比如只缓存了 GET 请求而你的应用发的是 POST 请求,那还是拿不到缓存数据。我之前就因为这个原因折腾了半天,最后发现是因为没缓存对应的请求类型。
总结一下,核心思路就是:优先查缓存,然后发网络请求,再用 catch 兜底处理网络异常。这样无论网络状态如何,你的应用都能尽量优雅地降级到缓存数据。