You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
            }
        });
    }
}

错误截图:
错误截图

问题分析与修复方案

核心问题:

  1. POST分支未返回响应Promise:onFetch是async函数,但POST处理逻辑里仅调用了Promise.resolve().then()却没有返回这个Promise,导致Service Worker无法获取到请求响应,触发报错。
  2. 请求体被重复消耗:直接读取event.request.text()会耗尽Request的body流,后续如果需要重新使用原请求会失败,必须先克隆请求再读取body。
  3. 遗漏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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 04:12:23