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

Service Worker中延迟失败请求:Promise始终判定为成功

问题分析与解决方案

嘿,我明白你遇到的问题了——你的Service Worker总是把请求判定为成功,哪怕实际返回了404或者500这种错误状态码,对吧?核心原因是fetch API的默认行为和你预期的不一样:

fetch只有在完全无法建立网络连接时(比如断网、DNS解析失败)才会触发reject;而HTTP错误状态码(4xx、5xx这类)并不会让Promise进入reject状态,它依然会resolve,只是返回的response对象里的ok属性会变成false。你的代码直接把fetch的resolve结果当成成功请求处理,自然会出现“明明请求失败却判定成功”的情况。

修正后的代码示例

我帮你调整一下fromNetwork函数,让它能正确识别HTTP请求失败的情况:

function fromNetwork(request) {
  return new Promise(function (fulfill, reject) {
    fetch(request).then(function (response) {
      // 关键:通过response.ok判断请求是否真正成功(状态码200-299)
      if (response.ok) {
        console.log('request succeed');
        fulfill(response);
      } else {
        console.log('request failed with status:', response.status);
        // 主动触发reject,让后续逻辑能捕获到失败
        reject(new Error(`Request failed with status ${response.status}`));
      }
    }, reject); // 保留这个reject,处理断网等纯网络层面的失败
  });
}

self.addEventListener('fetch', (event) => {
  event.respondWith(
    fromNetwork(event.request).catch((error) => {
      // 这里就是你要处理失败请求的地方:保存请求、返回兜底响应等
      console.log('Handling failed request:', error);
      // 示例:返回一个离线兜底页面/文本
      return new Response('Offline fallback content', { status: 503 });
    })
  );
});

关键改动说明

  • 新增response.ok判断:这个属性会在HTTP状态码处于200-299区间时返回true,其他情况返回false,这才是判断HTTP请求是否成功的标准方式。
  • 当请求实际失败时主动调用reject:这样后续的catch逻辑就能捕获到失败事件,你可以在这里实现“保存失败请求、延迟重试”的需求。
  • 保留原有的reject参数:用来处理纯网络层面的彻底失败(比如设备断网)。

额外小贴士

  • 如果你需要更精细的状态码控制,比如允许304(未修改)这类状态,可以直接检查response.status:if (response.status >= 200 && response.status < 400)。
  • 对于延迟重试的需求,你可以在catch里把请求的关键信息(URL、请求方法、请求体等)存入IndexedDB,之后借助Service Worker的Background Sync API来触发后台重试。

内容的提问来源于stack exchange,提问作者Victor Castro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:41:49