如何在Service Worker中返回localForage存储的Blob类型数据
问题原因
event.respondWith()要求必须返回Response类型的实例,你直接返回从IndexedDB取出的Blob对象,浏览器无法识别为合法响应,所以不生效- 存储逻辑存在错误:
networkResponse.blob()是异步方法,返回Promise对象,你直接将该Promise存入IndexedDB,实际存储的不是视频Blob数据
修正后的完整代码
const fetchHandler = async (event) => { const getResponse = async () => { const request = event.request; if( request.destination === 'video' ){ // 从IndexedDB读取缓存 const cachedBlob = await localforage.getItem('video'); // 将Blob包装为Response对象后返回 if( cachedBlob ) { return new Response(cachedBlob, { headers: { 'Content-Type': 'video/mp4' } }); } // 没有缓存走网络请求 const networkResponse = await fetch(event.request); // 先克隆响应,避免读取Blob后原始响应无法被返回 const responseClone = networkResponse.clone(); // 等待Blob读取完成后再存入IndexedDB const videoBlob = await responseClone.blob(); localforage.setItem('video', videoBlob).then(function (value) { console.log('视频缓存成功', value); }).catch(function(err) { console.error('视频缓存失败', err); }); // 返回网络请求的原始响应 return networkResponse; }else{ const openedCache = await caches.open(SW_CACHE_NAME); const cacheResponse = await openedCache.match(request); if (cacheResponse) return cacheResponse; const networkResponse = await fetch(event.request); // 克隆响应用于缓存写入 const responseClone = networkResponse.clone(); await openedCache.put(request, responseClone); // caches.put无返回值,直接返回原始网络响应 return networkResponse; } }; event.respondWith(getResponse()); };
改动说明
- 读取IndexedDB中的Blob后,通过
new Response()包装为标准响应对象,同时补充视频格式的响应头,保证浏览器可以正常识别解析视频 - 修复存储逻辑:先克隆网络响应,等待Blob异步读取完成后再存入IndexedDB,避免存储无效的Promise对象
- 修复非视频请求分支的逻辑错误:
caches.put方法没有返回值,原写法会返回undefined,修改为写入缓存后直接返回原始网络响应
内容的提问来源于stack exchange,提问作者Sébastien Renaudeau
相关产品推荐
相关产品推荐

