Blazor WASM PWA中Service Worker离线返回POST模拟响应报错
Blazor WASM PWA Service Worker离线POST请求延迟处理报错问题
我正在更新Blazor WASM PWA应用的Service Worker,要实现以下逻辑:
- 在线时,正常通过网络执行POST请求;
- 离线时,将POST请求保存到IndexedDb,等恢复在线后再执行,同时返回模拟响应让应用认为请求已成功完成。
但当前代码运行报错,相关代码如下:
async function onFetch(event) { const cache = await caches.open(cacheName); let cachedResponse = null; if (event.request.method === 'GET') { const shouldServeIndexHtml = event.request.mode === 'navigate'; const request = shouldServeIndexHtml ? 'index.html' : event.request; cachedResponse = await cache.match(request); if (cachedResponse == undefined) { const fetchResponse = await fetch(event.request.url); cache.put(event.request.url, fetchResponse.clone()); return fetchResponse; } return cachedResponse; } else if (event.request.method === 'POST') { var reqUrl = event.request.url; var authHeader = event.request.headers.get('Authorization'); // get the request body Promise.resolve(event.request.text()).then((payload) => { // if online, perform request as normal if (navigator.onLine) { return fetch(reqUrl, { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: payload }); } else { // if offline, save request to IndexedDb // saveIntoIndexedDb(reqUrl, authHeader, payload); // attempt to return mock response so application can continue to execute const myOptions = { status: 200, statusText: "Fabulous" }; return new Response(payload, myOptions); } }); } }
错误截图:
问题分析与修复方案
核心问题:
- POST分支未返回响应Promise:
onFetch是async函数,但POST处理逻辑里仅调用了Promise.resolve().then()却没有返回这个Promise,导致Service Worker无法获取到请求响应,触发报错。 - 请求体被重复消耗:直接读取
event.request.text()会耗尽Request的body流,后续如果需要重新使用原请求会失败,必须先克隆请求再读取body。 - 遗漏Authorization头:代码中获取了
authHeader但在线请求时未带入,导致请求可能因权限问题失败。
修正后的代码:
async function onFetch(event) { const cache = await caches.open(cacheName); let cachedResponse = null; if (event.request.method === 'GET') { const shouldServeIndexHtml = event.request.mode === 'navigate'; const request = shouldServeIndexHtml ? 'index.html' : event.request; cachedResponse = await cache.match(request); if (!cachedResponse) { const fetchResponse = await fetch(event.request.url); cache.put(event.request.url, fetchResponse.clone()); return fetchResponse; } return cachedResponse; } else if (event.request.method === 'POST') { const reqUrl = event.request.url; const authHeader = event.request.headers.get('Authorization'); // 克隆请求避免消耗原请求体 const clonedRequest = event.request.clone(); const payload = await clonedRequest.text(); if (navigator.onLine) { // 在线时带上所有必要头信息 const headers = new Headers({ 'Accept': 'application/json', 'Content-Type': 'application/json' }); if (authHeader) { headers.append('Authorization', authHeader); } return fetch(reqUrl, { method: 'POST', headers: headers, body: payload }); } else { // 离线时保存请求到IndexedDb(取消注释启用) // saveIntoIndexedDb(reqUrl, authHeader, payload); // 返回模拟响应让应用继续执行 const myOptions = { status: 200, statusText: "Fabulous" }; return new Response(payload, myOptions); } } }
关键修改点:
- 改用
await处理请求体读取,简化异步逻辑并确保函数返回Promise; - 克隆请求后再读取body,避免原请求流被耗尽;
- 在线请求时添加Authorization头,保证请求权限正确;
- 修正
cachedResponse == undefined为更严谨的!cachedResponse判断。
内容的提问来源于stack exchange,提问作者Trystan Lapinig-Wilcock
相关产品推荐
相关产品推荐

