← 返回题目列表

前端如何区分网络错误、HTTP 错误和业务错误?

中等 第 19 / 26 题 更新于 2026/07/29
前端网络错误处理HTTP请求封装

简化版

前端请求失败要区分三层:网络错误是请求没拿到有效 HTTP 响应,例如断网、DNS、CORS 被拦、超时取消;HTTP 错误是拿到了响应但状态码非 2xx,例如 401、403、500;业务错误是 HTTP 可能为 200,但响应体里的业务码表示失败。区分这些错误能决定提示文案、重试策略、登录跳转和监控归因。

详细版

Fetch 有一个容易误解的点:HTTP 500 不会让 Promise reject,只有网络层失败才 reject。

const res = await fetch('/api/user')
if (!res.ok) throw new HttpError(res.status)
const body = await res.json()
if (body.code !== 0) throw new BizError(body.code, body.message)
类型判断示例
网络错误fetch reject断网、CORS、超时
HTTP 错误!res.ok401、403、500
业务错误body code 非成功库存不足、参数错误

错误分层清楚,请求封装才不会把所有失败都提示成“网络异常”。

完整版教学

一、为什么要分层

用户看到的都是“失败”,但系统处理方式完全不同。断网可以提示检查网络,401 要跳登录,403 是权限问题,500 要上报服务异常,业务错误要展示业务文案。

如果全部混成一个错误类型,用户体验和监控都会很差。

二、网络错误

网络错误通常表示没有拿到正常 HTTP 响应。Fetch 会 reject。

常见原因包括:

  • 用户断网。
  • DNS 失败。
  • TLS 失败。
  • CORS 不允许。
  • 请求被 AbortController 取消。
  • 浏览器策略拦截。

CORS 失败在前端也常表现得像网络错误,因为浏览器不会把被拦响应暴露给 JS。

三、HTTP 错误

HTTP 错误是服务端返回了状态码,但状态码表示请求失败。Fetch 不会因为 404 或 500 自动 reject。

if (!response.ok) {
  throw new Error(`HTTP ${response.status}`)
}

这点是面试常见坑。

四、业务错误

很多接口使用统一响应:

{ "code": 10001, "message": "库存不足", "data": null }

HTTP 状态码可能仍是 200,但业务上失败。请求封装要解析业务 code。

五、不同错误如何处理

错误处理
网络错误提示网络/重试
超时提示稍后重试,可重试 GET
401清登录态并跳登录
403提示无权限
5xx服务异常,上报监控
业务错误展示后端业务文案

不要把所有错误都弹 toast,否则用户会被打扰。

六、请求封装建议

可以定义错误类:

class HttpError extends Error {
  constructor(public status: number, message = `HTTP ${status}`) {
    super(message)
  }
}

业务层捕获后根据类型处理。监控也能按类型统计。

七、常见误区与追问

  • 误区:HTTP 500 会让 fetch 自动 reject。 Fetch 只有网络失败才 reject,HTTP 状态要自己判断。
  • 误区:CORS 错误能读到服务端响应体。 浏览器会拦截响应,前端通常拿不到详细内容。
  • 误区:业务 code 失败就是网络失败。 它属于业务语义,提示和重试策略不同。
  • 追问:401 和 403 区别? 401 偏未认证,403 偏已认证但无权限。
  • 追问:超时算网络错误吗? 在前端封装里通常归为网络/取消类错误,但最好单独标记。
  • 追问:为什么要自定义错误类? 方便业务层和监控按类型处理,而不是解析字符串。

八、加强记忆

请求错误记成“三层失败”:没响应是网络错误,有响应状态坏是 HTTP 错误,状态正常但 code 失败是业务错误。分清层次,提示、重试和监控才准确。