前端常见 HTTP 状态码有哪些?
简化版
常见状态码包括 200 成功、201 创建成功、204 无内容、301/302 重定向、304 缓存未修改、400 参数错误、401 未登录、403 无权限、404 不存在、405 方法不允许、429 请求过多、500 服务端错误、502/503/504 网关或服务不可用。
详细版
分类记忆:
- 2xx:成功。
- 3xx:重定向或缓存。
- 4xx:客户端请求问题。
- 5xx:服务端问题。
前端常见处理:
- 401:清理登录态,引导登录。
- 403:提示无权限。
- 404:展示不存在或降级页。
- 429:提示频率限制,必要时重试。
- 500:提示服务异常。
- 502/503/504:网关或服务不可用,稍后重试。
状态码是 HTTP 层语义,业务 code 是业务层语义,两者不要混为一谈。
完整版教学
一、为什么要理解状态码
前端请求失败时,不能只弹一个“请求失败”。不同状态码代表不同问题,处理方式也不同。
401 和 403 都是访问失败,但前者是未认证,后者是已认证但无权限。处理逻辑完全不同。
二、缓存相关状态码
304 表示资源未修改,浏览器可以继续使用本地缓存。它不是错误,而是协商缓存正常命中。
301 是永久重定向,302 是临时重定向。前端路由、SEO、接口迁移都可能涉及重定向。
三、客户端和服务端错误
4xx 通常表示请求有问题,比如参数错、没登录、无权限、资源不存在。
5xx 通常表示服务端或网关异常。前端可以提示重试,但不能靠前端修复根因。
四、面试追问与工程落地
面试官可能问:“HTTP 200 但业务失败算成功吗?”
HTTP 层是成功的,说明请求响应正常完成;业务层可能失败,比如 { code: 1001, message: '余额不足' }。请求封装要分别处理 HTTP 状态和业务 code。
工程中统一请求层应把不同状态码转成一致的错误模型,页面只处理业务需要关注的结果。
五、容易混淆的成功与重定向语义
| 状态码 | 精确语义 | 前端常见动作 |
|---|---|---|
| 200 | 请求成功,有正常表示 | 解析响应体 |
| 201 | 资源已创建 | 可读取 Location/新资源 |
| 202 | 已接受但尚未完成 | 轮询任务或订阅结果 |
| 204 | 成功且无响应内容 | 不调用 JSON 解析空体 |
| 206 | 返回部分内容 | 断点下载/Range |
| 304 | 协商缓存未修改 | 浏览器复用缓存,不是普通 3xx 页面跳转 |
重定向也要区分方法是否保留:303 明确让后续使用 GET;307/308 保留原方法和请求体;301/302 在历史和客户端实现中可能发生 POST 转 GET。支付 POST 不能随意用 302 期待所有客户端保持方法。
状态码表达协议层结果,响应体里的业务 code 表达领域规则;两层都要有一致、可监控的语义。
六、错误模型、重试与数字例子
401 通常伴随认证挑战,表示缺少或无效认证;403 表示服务器理解请求但拒绝授权。统一拦截器遇到 100 个并发 401 时,不能同时发 100 次 refresh,应合并为一次刷新,其余请求等待并最多重放一次。
class ApiError extends Error {
constructor(kind, status, code, message, requestId) {
super(message)
Object.assign(this, { kind, status, code, requestId })
}
}
网络断开没有 HTTP status;超时可能由客户端主动终止;HTTP 500 有完整响应;业务余额不足可能是 409/422 配合业务 code。请求层应把这些来源归一化,但保留 status、业务 code、requestId 和可否重试,不能最后都变成字符串“系统异常”。
429 和 503 可能给 Retry-After,前端应有界等待;400、401、403 通常不会靠原样重试自愈。日志和监控按状态族、接口与版本聚合,单个页面不要各写一套跳转规则。
重定向还要防循环:客户端可设置最大跳转次数,服务端监控同一 URL 链路。301/308 会被缓存,错误永久重定向的修复成本通常高于临时重定向。
客户端埋点应保留原始状态码和业务错误码,不能全部折叠成“请求失败”,否则无法区分协议语义与业务裁决。
七、常见误区与追问
- 误区:只要响应体业务 code 失败,HTTP 就必须返回 200。 应尽量让 HTTP 状态表达协议和资源处理结果,业务 code 补充领域细节。
- 误区:401 和 403 可以互换。 前者偏认证缺失/失效,后者偏已理解但无权访问。
- 误区:204 响应可以照常调用
response.json()。 204 没有消息体,盲目解析可能抛错。 - 追问:202 为什么不是“处理完成”? 它只表示请求被接受,最终任务可能稍后成功或失败。
- 追问:304 为什么不是业务成功响应? 它服务于条件请求,表示客户端可复用已有缓存表示。
- 追问:307/308 与 301/302 最大区别是什么? 307/308 明确保持原请求方法和请求体。
- 追问:网络错误为什么没有 status=0 就统一处理? fetch 的网络失败通常直接拒绝,status 只属于收到的 HTTP Response,应区分来源。
八、加强记忆
- 按族定位:2xx 成功,3xx 重定向/缓存,4xx 请求侧,5xx 服务侧。
- 重点区分:201 已创建、202 已接受、204 无正文、206 部分内容。
- 身份语义:401 处理认证,403 展示无权限,不要循环跳登录。
- 重定向方法:303 转 GET,307/308 保留方法和请求体。
- 错误建模:网络、取消、HTTP、业务错误统一外形但保留原始信息。
- 重试谨慎:尊重 Retry-After、幂等性和最大预算,不重试确定性错误。