目录
Axios 介绍
Axios 是基于 XMLHttpRequest(XHR) 和 Promise 进行封装的 HTTP 客户端。
它的核心实现依赖于以下技术:
XMLHttpRequest(XHR)
- 在浏览器环境下,Axios 使用
XMLHttpRequest
发送 HTTP 请求,并基于它进行封装,提供更简洁的 API 和更好的错误处理机制。 - 例如,它支持请求和响应的拦截器、超时设置、请求取消等功能,而这些都需要额外的封装才能在
XMLHttpRequest
中实现。
- 在浏览器环境下,Axios 使用
Node.js 的 http 模块
- 在 Node.js 环境下,Axios 使用
http
或https
模块代替XMLHttpRequest
发送 HTTP 请求,从而实现跨环境的兼容性。
- 在 Node.js 环境下,Axios 使用
Promise
- Axios 的 API 是基于
Promise
设计的,所有请求都会返回一个Promise
,支持async/await
,比传统的XMLHttpRequest
更加方便。
- Axios 的 API 是基于
拦截器(Interceptors)
- 通过
request
和response
拦截器,Axios 允许在请求或响应到达应用程序之前,对其进行修改,比如添加请求头、处理错误、全局 loading 等。
- 通过
取消请求(Cancel Token)
- 依赖
AbortController
或者CancelToken
(Axios 0.x 版本提供),可以在特定条件下取消未完成的 HTTP 请求。
- 依赖
自动 JSON 解析
- Axios 默认会将 JSON 响应数据自动解析成 JavaScript 对象,而
XMLHttpRequest
需要手动解析。
- Axios 默认会将 JSON 响应数据自动解析成 JavaScript 对象,而
并发请求管理
- 通过
axios.all()
和axios.spread()
,支持并行发送多个请求,并在所有请求完成后进行处理。
- 通过
总结来说,Axios 的底层实现主要基于 XMLHttpRequest(浏览器端)或 Node.js http 模块(服务端),同时结合 Promise、拦截器、取消请求等高级特性,提供了比原生 API 更易用的 HTTP 请求功能。
拦截器特性
Axios 拦截器(Interceptors)可以在请求发送前或响应返回后进行处理,常用于全局请求配置、错误处理、权限校验、自动重试等场景。以下是几个实际应用示例:
1. 统一添加 Token(请求拦截器)
场景:
需要在所有请求的 headers
中添加 Authorization
头部,例如 JWT Token。
import axios from "axios";
// 创建 axios 实例
const api = axios.create({
baseURL: "https://api.example.com",
timeout: 5000,
});
// 请求拦截器
api.interceptors.request.use(
config => {
const token = localStorage.getItem("token"); // 从本地存储获取 token
if (token) {
config.headers.Authorization = `Bearer ${token}`; // 设置 Authorization 头部
}
return config;
},
error => Promise.reject(error)
);
// 使用 axios 实例
api.get("/user/profile").then(response => console.log(response.data));
📌 效果:
- 所有请求都会自动附带
Authorization
头部,避免手动在每个请求中添加。
2. 处理 401 未授权(响应拦截器)
场景:
当后端返回 401 Unauthorized
,表示 Token 失效,应该自动跳转到登录页。
api.interceptors.response.use(
response => response,
error => {
if (error.response?.status === 401) {
console.error("身份认证失败,跳转到登录页...");
window.location.href = "/login"; // 重定向到登录页面
}
return Promise.reject(error);
}
);
📌 效果:
- 如果请求返回
401
,用户会被自动跳转到登录页,而不会继续执行后续逻辑。
3. 统一处理错误信息(响应拦截器)
场景:
后端返回错误时,拦截器可以解析 error.response.data
,并弹出错误提示。
import { message } from "antd"; // 适用于 Ant Design 的 message 组件
api.interceptors.response.use(
response => response,
error => {
if (error.response) {
const { status, data } = error.response;
const errorMsg = data.message || "服务器错误";
message.error(`请求失败 (${status}): ${errorMsg}`);
} else {
message.error("网络异常,请检查你的连接");
}
return Promise.reject(error);
}
);
📌 效果:
- 400、500 等错误时,自动弹出友好的错误提示。
4. 请求 Loading 状态管理
场景:
在请求发起时显示 Loading 状态,请求结束后自动隐藏。
import { message } from "antd";
let requestCount = 0;
function showLoading() {
if (requestCount === 0) {
message.loading("加载中...", 0);
}
requestCount++;
}
function hideLoading() {
requestCount--;
if (requestCount === 0) {
message.destroy(); // 关闭 loading
}
}
// 请求拦截器:增加 Loading
api.interceptors.request.use(config => {
showLoading();
return config;
});
// 响应拦截器:移除 Loading
api.interceptors.response.use(
response => {
hideLoading();
return response;
},
error => {
hideLoading();
return Promise.reject(error);
}
);
📌 效果:
- 多个请求时,只显示一个 Loading,所有请求完成后才关闭。
5. 自动重试请求(如 429 过载)
场景:
如果服务器返回 429 Too Many Requests
,可以实现自动重试,避免短时间内请求失败。
api.interceptors.response.use(
response => response,
async error => {
const { response, config } = error;
if (response?.status === 429 && !config.__isRetryRequest) {
config.__isRetryRequest = true;
console.warn("请求过载,2 秒后重试...");
await new Promise(resolve => setTimeout(resolve, 2000));
return api(config); // 重新请求
}
return Promise.reject(error);
}
);
📌 效果:
- 如果服务器返回
429
,拦截器会等待 2 秒后自动重试一次。
6. 数据格式转换(响应拦截器)
场景:
后端返回的数据格式不符合前端要求,需要在拦截器中转换。
api.interceptors.response.use(response => {
if (response.data && response.data.result) {
return response.data.result; // 提取需要的 `result` 数据
}
return response.data;
});
📌 效果:
- 假设后端返回
{ success: true, result: { name: "Tom" } }
,前端直接拿到{ name: "Tom" }
。
7. 记录请求日志(请求拦截器 + 响应拦截器)
场景:
在开发模式下,打印请求和响应日志,方便调试。
api.interceptors.request.use(config => {
console.log("🚀 请求:", config.method?.toUpperCase(), config.url, config.data);
return config;
});
api.interceptors.response.use(
response => {
console.log("✅ 响应:", response.config.url, response.data);
return response;
},
error => {
console.error("❌ 请求失败:", error.config?.url, error.response?.status);
return Promise.reject(error);
}
);
📌 效果:
- 在开发者工具控制台中,能看到请求和响应的日志信息,方便调试。
总结
拦截器类型 | 应用场景 | **示例代码 |
---|---|---|
请求拦截器 | 统一添加 Token | config.headers.Authorization = Bearer ${token} |
请求拦截器 | 全局 Loading 处理 | showLoading() 和 hideLoading() |
响应拦截器 | 处理 401 未授权 | if (error.response.status === 401) { window.location.href = "/login"; } |
响应拦截器 | 统一错误提示 | message.error(error.response.data.message); |
响应拦截器 | 处理 429 过载自动重试 | await new Promise(resolve => setTimeout(resolve, 2000)); return api(config); |
响应拦截器 | 数据格式转换 | return response.data.result; |
拦截器 | 请求 & 响应日志 | console.log("🚀 请求:", config) |
结论
Axios 拦截器非常强大,能帮助我们在全局范围内 统一管理请求和响应,减少重复代码,提升可维护性。实际项目中,可以根据需求选择合适的拦截器组合,提升开发效率!