🧩 前端工程实战:HTTP 请求拦截与错误处理的正确姿势
“接口请求失败了?怎么都没提示!”
“后端 401 了我还在页面继续点……”
如果你也在项目中遇到过类似的尴尬场面,那你可能需要好好了解一下前端的 HTTP 请求拦截与错误处理机制。
在 Vue/React 等现代前端项目中,接口请求是日常开发的核心。而如何在全局优雅地管理这些请求 —— 包括统一加 token、统一错误弹窗、自动跳转登录、捕获网络异常 —— 是项目健壮性的重要保障。
本文将通过 axios 为例,讲解如何拦截请求与响应、集中处理异常、提升用户体验与开发效率。
📦 什么是请求拦截与响应拦截?
使用 axios 时,可以通过拦截器为每个请求/响应 统一加料或做处理,如同为接口套上中间件。
axios.interceptors.request.use(config => { config.headers.Authorization = getToken(); return config; }, error => Promise.reject(error));
axios.interceptors.response.use(response => { return response.data; }, error => { handleError(error); return Promise.reject(error); });
|
✨ 请求拦截:统一处理请求前的操作
请求拦截通常用于:
| 用途 |
示例 |
| 添加鉴权 token |
加入 Authorization 请求头 |
| 加统一前缀或 baseUrl |
适配代理或环境 |
| 发起 loading 状态 |
显示页面 loading 动效 |
| 加入 traceId / sessionId |
后端日志定位、流程追踪 |
示例代码:
axios.interceptors.request.use(config => { const token = localStorage.getItem('token'); if (token) { config.headers['Authorization'] = `Bearer ${token}`; } config.headers['X-Request-Id'] = generateUUID(); return config; }, error => { return Promise.reject(error); });
|
⚠ 响应拦截:统一处理返回结果和错误
响应拦截可以做两件事:
✅ 1. 数据格式统一处理
很多接口返回格式如:
{ "code": 0, "data": { ... }, "msg": "成功" }
|
可以统一处理成:
axios.interceptors.response.use(response => { const { code, data, msg } = response.data; if (code === 0) { return data; } else { ElMessage.error(msg || '请求失败'); return Promise.reject(new Error(msg)); } });
|
这样组件中就能直接使用:
const res = await api.getUser();
|
❌ 2. 错误处理(401、500、断网等)
axios.interceptors.response.use( res => res, error => { const status = error.response?.status; if (status === 401) { ElMessage.warning('登录已失效,请重新登录'); router.push('/login'); } else if (status === 500) { ElMessage.error('服务器开小差了,请稍后重试'); } else if (!error.response) { ElMessage.error('网络异常,请检查网络连接'); } else { ElMessage.error(error.response.data?.msg || '请求失败'); } return Promise.reject(error); } );
|
🛠 实战推荐策略
在实际项目中,我们建议这样组织 HTTP 拦截与错误处理逻辑:
✅ 拦截器注册模块化封装
import axios from 'axios'; import { ElMessage } from 'element-plus';
const instance = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 10000, });
instance.interceptors.request.use(config => { const token = localStorage.getItem('token'); if (token) config.headers['Authorization'] = `Bearer ${token}`; return config; });
instance.interceptors.response.use( res => { const { code, data, msg } = res.data; if (code === 0) return data; ElMessage.error(msg || '请求失败'); return Promise.reject(new Error(msg)); }, error => { const status = error.response?.status; if (status === 401) { ElMessage.warning('登录过期,请重新登录'); location.href = '/login'; } else { ElMessage.error('网络错误或服务异常'); } return Promise.reject(error); } );
export default instance;
|
✅ API 调用示例
import request from '@/utils/http';
export function getUserInfo() { return request.get('/user/info'); }
|
📌 常见错误场景处理建议
| 错误类型 |
建议做法 |
| 401 未授权 |
清 token,跳转登录页 |
| 403 权限不足 |
弹出提示,无跳转 |
| 404 接口不存在 |
提示后上报错误日志 |
| 500 后端异常 |
弹窗提示、允许用户重试 |
| 网络超时 / 断网 |
提示网络问题,可选 loading fallback |
| code !== 0 |
按后端定义规则提示用户 |
🎯 总结
- ✅ 使用请求拦截器统一加 token、traceId;
- ✅ 使用响应拦截器统一处理 code 判断与异常提示;
- ✅ 错误处理应清晰有反馈,不让用户“黑盒使用”;
- ✅ 拦截器逻辑推荐模块化封装,避免重复代码;
- ✅ 项目越大,统一错误处理带来的收益越明显。
你还可以进一步引入:
- 🔍
Sentry 等错误监控工具,记录异常
- ⏱ loading 状态统一处理(如配合全局 loading 管理器)
- 🚥 请求取消功能(如路由切换时中断无用请求)
你项目中是如何处理 HTTP 请求与错误的?欢迎留言分享经验!