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

如何区分Fetch请求中的网络错误与主动Promise链中断

Fetch请求中区分HTTP状态错误与网络错误的实现方案

问题场景

现有JavaScript代码设计预期为:当Web端点返回2xx类(即200区间的成功状态码)响应时执行对应成功逻辑,返回404状态码时执行专属处理逻辑,返回非404的其他HTTP状态码时执行对应错误逻辑,同时需要正确处理网络异常场景。
原有实现代码如下:

fetch('https://httpstat.us/404')
  .then((r) => {
    if (r.ok) {
      console.log(`response 200-ish`)
      return r // 进入下一个.then()
    } else {
      console.log(`response is not 200-ish`)
      return Promise.reject(r.status) // 在此处中断成功Promise链
    }
  })
  .then((r) => {
    console.log('do stuff for 200-ish')
  })
  .catch((err) => {
    if (err === 404) {
      console.log('do 404 stuff')
    } else {
      console.log('do stuff because of another response from the API')
    }
    // 此处无法区分网络错误与其他HTTP状态错误
  })

现有代码问题

不同场景下的运行表现如下:

  • 请求https://httpstat.us/200时,代码运行符合预期
  • 请求https://httpstat.us/404时,代码运行符合预期
  • 请求https://httpstat.us/500(既非200也非404,但属于API服务器正常返回的响应)时,代码仅碰巧运行符合预期
  • 请求https://httpstat.usXXXXXXXX/500(非法URL,会触发网络错误)时,代码运行不符合预期

问题根源:catch块中最后的else分支会捕获所有未被显式校验的错误,无法区分「主动中断Promise链抛出的HTTP状态码错误」和「真实发生的网络层错误」。

实现方案

核心思路:不要直接抛出裸的状态码数值,而是用带专属标识的错误对象包装HTTP响应错误,和原生网络错误做明确区分。
原生Fetch触发的网络错误本身是TypeError类型实例,只要给主动抛出的HTTP错误加上可识别的专属标记,就能在catch块中精准判断错误来源。

修正后代码

// 自定义HTTP错误类,专门包装服务器返回的非2xx响应错误
class HttpError extends Error {
  constructor(status, response) {
    super(`HTTP request failed with status ${status}`)
    this.name = 'HttpError'
    this.status = status // 存储HTTP状态码
    this.response = response // 存储原始响应对象,可按需读取响应体
  }
}

fetch('https://httpstat.us/404')
  .then((r) => {
    if (r.ok) {
      console.log(`response 200-ish`)
      return r
    }
    // 非2xx响应统一抛出自定义HttpError,和原生网络错误做区隔
    throw new HttpError(r.status, r)
  })
  .then((r) => {
    console.log('do stuff for 200-ish')
  })
  .catch((err) => {
    // 优先判断是否为主动抛出的HTTP响应错误
    if (err instanceof HttpError) {
      if (err.status === 404) {
        console.log('do 404 stuff')
      } else {
        console.log(`handle other HTTP error, status code: ${err.status}`)
      }
    } else {
      // 剩余错误为原生网络错误,包含断网、非法URL、CORS跨域拦截等场景
      console.log('handle network error', err)
    }
  })

方案说明

  • 自定义HttpError类继承原生Error,专门承载服务器正常返回的非2xx响应错误,除状态码外还可按需附加响应体、请求参数等上下文信息
  • 所有非2xx响应统一抛出HttpError实例,不再直接抛出裸数字
  • catch块中先通过instanceof判断错误类型,属于HttpError则按状态码分支处理业务逻辑,否则统一按网络异常处理
  • 如果不想额外定义类,也可以用更轻量的实现:抛出错误时给普通对象加专属标记,比如throw { type: 'HTTP_ERROR', status: r.status },catch块中先判断err.type === 'HTTP_ERROR'再处理状态码即可。自定义类的方式语义更清晰,也能保留完整错误栈方便调试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 13:27:17