Web 项目中 Axios 与 HTTP 状态码的正确打开方式
在日常 Web 开发中,我们几乎每天都在和 axios 打交道。但你真的理解它与 HTTP 状态码之间的关系吗?很多开发者对状态码存在误解,导致错误处理逻辑混乱、用户体验差,甚至埋下线上隐患。
本文将结合实战经验,系统梳理 HTTP 状态码分类、常见误区、Axios 默认行为及增强策略,帮助你构建更健壮的前端请求体系。
一、关于状态码的常见错误认知
❌ 误区1:“404 是服务器的问题”
真相:404 属于 4xx 客户端错误。它表示“你请求的资源不存在”,责任在客户端(比如拼错了 URL、访问了已删除的页面)。服务器只是如实告知结果,这恰恰说明服务正常!
✅ 判断标准:如果修正请求(改路径、加参数)就能成功 → 就是客户端问题。
❌ 误区2:“只要返回了 JSON 错误信息,就是业务错误,不算异常”
真相:Axios 的成功/失败判断只看状态码是否在 2xx 范围内,与响应体内容无关。
// 即便服务器返回 { code: 400, msg: "用户名不能为空" }
// 只要状态码是 400,Axios 就会进入 .catch()
axios.post('/register', { username: '' })
.then(res => { /* 不会执行 */ })
.catch(err => { /* 会执行!*/ });
⚠️ 很多团队把“业务错误”和“HTTP 错误”混为一谈,导致前端不得不在 .catch() 里写大量业务逻辑,代码难以维护。
❌ 误区3:“304 Not Modified 是错误”
真相:304 表示缓存命中,无需重新下载资源,是一种成功的优化行为。但它属于 3xx 重定向类,Axios 默认将其视为失败(因为不是 2xx)!
这意味着如果你不做特殊处理,所有触发 304 的请求都会进 .catch() —— 这显然不合理。
二、HTTP 状态码权威分类(开发必备)
所有 4xx 状态码都表示「客户端错误」(Client Error),
所有 5xx 状态码才表示「服务端错误」(Server Error)。
这是 HTTP 协议的官方定义(RFC 7231 等标准)。
✅ 正确分类
| 状态码范围 | 类型 | 责任方 | 含义说明 |
|---|---|---|---|
| 4xx | 客户端错误 | 客户端 | 请求有问题:格式错、权限不足、资源不存在、方法不对等。服务器理解请求,但拒绝处理或无法处理(因为客户端没按规矩来)。 |
| 5xx | 服务端错误 | 服务端 | 服务器内部出错:代码崩溃、数据库连不上、网关超时等。即使客户端请求完全正确,服务器也无法正常响应。 |
❌ 常见误解澄清
有些人会误以为:
- “404 是服务器没找到资源,所以是服务端的问题?”
- “403 是服务器禁止我访问,是不是服务器配置错了?”
但实际上:
- 404:客户端请求了一个不存在的路径(比如拼错 URL),服务器如实告知“没有这个东西”——这是对客户端错误请求的合理响应。
- 403:客户端已认证,但试图访问无权访问的资源(比如普通用户访问
/admin),服务器拒绝——这是客户端越权,不是服务器故障。
👉 关键判断标准:
如果修正客户端的请求(改 URL、加 Token、换参数、换方法等)就能成功,那就是 4xx(客户端错误)。
如果客户端请求完全正确,但服务器依然挂了或返回异常,那就是 5xx(服务端错误)。
📌 举例对比
| 状态码 | 场景 | 错误类型 | 谁该负责修复? |
|---|---|---|---|
400 Bad Request | POST 提交的 JSON 缺少必填字段 | 客户端 | 前端/调用方检查参数 |
401 Unauthorized | 没带 Token 或 Token 过期 | 客户端 | 前端应重新登录或刷新 Token |
403 Forbidden | 普通用户访问管理员接口 | 客户端 | 前端不应发起此请求,或提示无权限 |
404 Not Found | 请求了 /api/user/999(ID 不存在) | 客户端 | 前端应确保 ID 有效,或处理“未找到”情况 |
429 Too Many Requests | 短时间内发太多请求被限流 | 客户端 | 前端应加节流或提示用户稍后再试 |
500 Internal Server Error | 服务器代码抛异常(如空指针) | 服务端 | 后端需查日志修复 bug |
502 Bad Gateway | Nginx 无法连接后端服务 | 服务端 | 运维/后端检查服务是否宕机 |
503 Service Unavailable | 服务器维护或过载 | 服务端 | 后端扩容或等待恢复 |
💡 在 Axios 中如何区分?
axios.get('/some-api')
.catch(error => {
if (error.response) {
const status = error.response.status;
if (status >= 400 && status < 500) {
console.log('⚠️ 客户端错误(4xx):', status);
// 通常提示用户:检查输入、重新登录、无权限等
} else if (status >= 500) {
console.log('🔥 服务端错误(5xx):', status);
// 通常提示:“系统繁忙,请稍后再试” 或 上报监控
}
} else {
// 网络错误(如断网、DNS 失败)——也属于客户端环境问题
console.log('🌐 网络连接失败');
}
});
✅ 总结
- 4xx = 客户端错了 → 前端/调用方需要修正请求。
- 5xx = 服务端错了 → 后端需要排查和修复。
- 不要混淆“服务器返回了错误”和“服务器自身出错”:4xx 是服务器正确地拒绝了错误请求,这恰恰说明服务器工作正常!
三、Axios 中关于状态码的补充逻辑
1. 自定义“成功”范围:validateStatus
默认只有 2xx 成功。但我们可以扩展:
const instance = axios.create({
baseURL: '/api',
// 允许 2xx 和 304 都算成功
validateStatus: (status) => {
return (status >= 200 && status < 300) || status === 304;
}
});
这样 304 就能进入 .then(),避免在 .catch() 里处理缓存逻辑。
2. 响应拦截器:统一错误分类与提示
instance.interceptors.response.use(
// 成功回调
(response) => {
// 可在此处解包业务数据(如 return response.data.data)
return response;
},
// 失败回调
(error) => {
const { response } = error;
if (response) {
const { status, data } = response;
// 客户端错误(4xx)
if (status >= 400 && status < 500) {
switch (status) {
case 401:
// Token 失效,跳转登录
window.location.href = '/login';
break;
case 403:
message.error('无权限访问');
break;
case 404:
message.error('请求资源不存在');
break;
case 429:
message.warning('操作太频繁,请稍后再试');
break;
default:
message.error(data?.message || '请求参数错误');
}
}
// 服务端错误(5xx)
else if (status >= 500) {
message.error('系统繁忙,请稍后再试');
// 可上报 Sentry / 自研监控
reportErrorToMonitor(error);
}
}
// 网络错误(无 response)
else {
message.error('网络连接失败,请检查网络');
}
// 务必 reject,让上层 .catch 能捕获
return Promise.reject(error);
}
);
3. 区分“HTTP 错误”与“业务错误”
更优雅的做法:所有请求都返回 200,在响应体中用 code 字段表示业务状态。
// 成功
{ "code": 0, "data": { ... }, "msg": "ok" }
// 业务失败
{ "code": 1001, "data": null, "msg": "用户名已存在" }
此时 Axios 永远走 .then(),前端只需判断 res.data.code:
instance.interceptors.response.use(
(response) => {
const { code, data, msg } = response.data;
if (code !== 0) {
message.error(msg);
return Promise.reject(new Error(msg));
}
return data; // 只返回业务数据
}
);
✅ 优点:逻辑清晰,
.catch()仅处理网络/服务器崩溃等真正异常。
⚠️ 缺点:违背 RESTful 原则,调试时状态码信息缺失。
建议:内部系统可用此方案;对外 API 或追求规范的项目,仍推荐使用标准 HTTP 状态码。
四、总结:最佳实践清单
- ✅ 明确责任边界:4xx 是前端问题,5xx 是后端问题。
- ✅ 不要在
.catch()里写业务逻辑,除非你使用“全 200”方案。 - ✅ 304 应视为成功,通过
validateStatus修正 Axios 默认行为。 - ✅ 统一错误提示:在响应拦截器中按状态码分类处理。
- ✅ 关键 5xx 错误上报监控,便于快速发现线上问题。
- ✅ 合理选择方案:标准状态码(规范) vs 全 200(简化前端)。
最后提醒:HTTP 状态码是 Web 的通用语言。用好它,你的 API 更专业,你的前端更健壮,你的协作更高效。
觉得有用?点赞 + 收藏,让更多人少踩坑! 💪
参考资料: