Axios 是一个基于 Promise 的 HTTP 客户端,它可以用于浏览器和 Node.js。其核心原理主要包括以下几个部分:
- 请求流程
Axios 的请求流程主要包括以下步骤:
创建实例:axios.create() 方法可以创建一个具有默认配置的 Axios 实例。
请求拦截器:在请求发送前,可以使用 axios.interceptors.request.use() 进行修改,如添加 token、修改 headers。
请求适配器:在浏览器环境中,Axios 通过 XMLHttpRequest(XHR) 发送请求,在 Node.js 环境中使用 http 模块。
响应拦截器:在请求返回后,axios.interceptors.response.use() 允许对响应数据进行处理,比如格式化数据或错误处理。
- 核心模块
Axios 主要由以下几个核心模块组成:
(1) Axios 类
Axios 是核心类,所有的请求都通过 Axios.prototype.request(config) 进行处理:
class Axios {
constructor(defaultConfig) {
this.defaults = defaultConfig;
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager(),
};
}
request(config) {
// 处理请求配置
config = mergeConfig(this.defaults, config);
// 构造拦截器链
let chain = [
{ fulfilled: dispatchRequest, rejected: undefined }
];
// 先添加请求拦截器
this.interceptors.request.forEach(interceptor => {
chain.unshift(interceptor);
});
// 再添加响应拦截器
this.interceptors.response.forEach(interceptor => {
chain.push(interceptor);
});
// 执行拦截器链
let promise = Promise.resolve(config);
while (chain.length) {
const { fulfilled, rejected } = chain.shift();
promise = promise.then(fulfilled, rejected);
}
return promise;
}
}
(2) 拦截器 (InterceptorManager)
Axios 内部使用 InterceptorManager 管理拦截器,它的结构如下:
class InterceptorManager {
constructor() {
this.handlers = [];
}
use(fulfilled, rejected) {
this.handlers.push({ fulfilled, rejected });
}
forEach(fn) {
this.handlers.forEach(fn);
}
}
拦截器的执行顺序:
请求拦截器:先进后出(后添加的先执行)
响应拦截器:先进先出(先添加的先执行)
(3) 适配器 (adapters)
Axios 需要兼容不同的运行环境,因此通过适配器模式进行封装:
在 浏览器 环境下,使用 XMLHttpRequest 发送请求:
function xhrAdapter(config) {
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
request.open(config.method.toUpperCase(), config.url, true);
request.onload = function () {
resolve({
data: request.responseText,
status: request.status,
headers: parseHeaders(request.getAllResponseHeaders()),
config,
});
};
request.onerror = function () {
reject(new Error("Network Error"));
};
request.send(config.data);
});
}
在 Node.js 环境下,使用 http 模块:
function httpAdapter(config) {
return new Promise((resolve, reject) => {
const http = require('http');
const req = http.request(config.url, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve({ data, status: res.statusCode }));
});
req.on('error', reject);
req.write(config.data || '');
req.end();
});
}
(4) dispatchRequest 发送请求
dispatchRequest 负责选择适配器并发送请求:
function dispatchRequest(config) {
const adapter = config.adapter || (typeof XMLHttpRequest !== 'undefined' ? xhrAdapter : httpAdapter);
return adapter(config).then(response => {
return response;
});
}
- Axios 其他功能
(1) axios.create()
可以创建一个自定义实例,带有默认 config:
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 1000,
});
instance.get('/user');
(2) 取消请求 (CancelToken)
Axios 允许取消请求,核心原理是 AbortController:
const controller = new AbortController();
axios.get('/user', { signal: controller.signal }).catch(err => console.log(err));
// 取消请求
controller.abort();
(3) 并发请求 (axios.all())
可以使用 Promise.all 进行并发请求:
axios.all([axios.get('/user'), axios.get('/posts')])
.then(axios.spread((user, posts) => {
console.log(user.data, posts.data);
}));
- 总结
核心架构
-
Axios 类:处理请求逻辑
-
InterceptorManager:管理请求/响应拦截器
-
dispatchRequest:调用适配器发送请求
-
xhrAdapter & httpAdapter:兼容不同环境
拦截器机制
先进后出执行请求拦截器
先进先出执行响应拦截器
功能
axios.create():创建实例
axios.CancelToken:取消请求
axios.all():并发请求
这样,Axios 通过模块化设计,提供了一种可扩展、兼容性强的 HTTP 请求解决方案。
Axios 之所以被称为"基于 Promise 的 HTTP 客户端",是因为它的内部实现依赖于 Promise 机制 来处理异步请求,并提供了链式调用的能力。
- 传统回调与 Promise 的区别
在使用 XMLHttpRequest 进行网络请求时,通常需要通过 回调函数 处理异步请求:
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
};
xhr.send();
这种写法可读性较差,且多个异步操作嵌套时会形成 回调地狱。
而 Promise 允许我们以更清晰的方式处理异步操作:
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
Axios 也是采用 Promise 方式 来封装 XMLHttpRequest,避免了回调地狱,并提供更强的扩展性。
- Axios 如何使用 Promise
Axios 的核心方法 axios(config) 或 axios.get(url) 返回的其实是一个 Promise:
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data); // 请求成功时处理数据
})
.catch(error => {
console.error(error); // 请求失败时捕获错误
});
从外部使用上,Axios 提供了标准的 Promise 语法,可以使用 .then() 处理成功结果,使用 .catch() 处理错误,还可以使用 .finally() 进行清理工作。
- Axios 内部基于 Promise 处理请求
Axios 在内部通过 Promise.resolve(config) 让请求流程变成一个 Promise 链:
Axios.prototype.request = function (config) {
let promise = Promise.resolve(config);
// 处理拦截器
const chain = [dispatchRequest, undefined]; // 发送请求的函数
this.interceptors.request.forEach(interceptor => {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});
this.interceptors.response.forEach(interceptor => {
chain.push(interceptor.fulfilled, interceptor.rejected);
});
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
};
Promise.resolve(config) 确保整个流程是异步执行的。
chain 维护一个拦截器队列,使得 请求拦截器 -> 发送请求 -> 响应拦截器 形成一个 Promise 链。
最终,返回的 Promise 允许调用 .then()、.catch() 处理异步逻辑。
- 支持 Promise 并发操作
Axios 还支持 axios.all() 进行多个异步请求的并发处理:
axios.all([
axios.get('/user'),
axios.get('/orders')
])
.then(axios.spread((user, orders) => {
console.log(user.data, orders.data);
}))
.catch(error => console.error(error));
axios.all() 的本质是基于 Promise.all(),它会并行执行多个请求,并在所有请求完成后返回结果。
-
总结
-
Axios 采用 Promise 进行封装,避免了 XMLHttpRequest 的回调嵌套问题,使代码更加简洁。
-
内部基于 Promise 处理请求拦截器、发送请求、响应拦截器,形成完整的 Promise 链。
-
返回标准 Promise 对象,支持 .then() 处理成功结果,.catch() 处理错误,.finally() 进行清理。
-
支持 Promise 并发操作,比如 axios.all(),提升异步操作的能力。
因此,Axios 是 基于 Promise 设计的 HTTP 客户端,它利用 Promise 提供的链式调用、错误处理、并发能力,让网络请求管理更加优雅。
Axios 被称为 HTTP 客户端,主要是因为它封装了 HTTP 请求 的发送、处理和管理,提供了类似于浏览器 fetch 或 XMLHttpRequest 的功能,但比原生 API 更强大和易用。以下是 Axios 作为 HTTP 客户端 的关键特性:
- Axios 是一个 HTTP 客户端
Axios 主要用于 向服务器发送 HTTP 请求 并 处理 HTTP 响应,它支持:
GET(获取资源)
POST(提交数据)
PUT(更新数据)
DELETE(删除数据)
PATCH(部分更新)
以及 HEAD、OPTIONS 等请求方法
示例:
axios.get('https://api.example.com/users')
.then(response => console.log(response.data))
.catch(error => console.error(error));
这个请求会发送 GET 请求到 https://api.example.com/users,然后 Axios 作为 HTTP 客户端 处理返回的响应。
- Axios 依赖 HTTP 协议
Axios 本质上是对 HTTP 协议的封装:
在 浏览器环境 下,使用 XMLHttpRequest 发送 HTTP 请求。
在 Node.js 环境 下,使用 http 或 https 模块发送 HTTP 请求。
适配器示例:
const adapter = typeof XMLHttpRequest !== 'undefined' ? xhrAdapter : httpAdapter;
Axios 自动选择合适的 HTTP 传输方式,确保在不同环境下都能发送 HTTP 请求。
- Axios 处理 HTTP 请求与响应
Axios 作为 HTTP 客户端,提供了请求和响应处理功能,包括:
请求拦截(修改请求,例如添加 token)
自动解析 JSON
处理 HTTP 状态码
错误处理
请求超时控制
跨域请求
示例:
axios.interceptors.request.use(config => {
config.headers.Authorization = 'Bearer token';
return config;
});
这里的拦截器为 HTTP 请求 添加身份验证头部,这正是 HTTP 客户端的常见功能之一。
- Axios 提供 HTTP 相关功能
Axios 作为 HTTP 客户端,提供了一些常见的 HTTP 相关功能:
- 自动解析响应数据
axios.get('/data').then(response => console.log(response.data));
Axios 自动将 JSON 响应解析为 JavaScript 对象,而 XMLHttpRequest 需要手动 JSON.parse(responseText)。
- 请求超时控制
axios.get('/slow-api', { timeout: 5000 })
.catch(error => console.log('请求超时', error));
超过 5s 后会自动取消请求。
- 设置请求头
axios.post('/submit', data, {
headers: { 'Content-Type': 'application/json' }
});
可以轻松设置 HTTP 头部。
- 取消 HTTP 请求
const controller = new AbortController();
axios.get('/data', { signal: controller.signal });
// 取消请求
controller.abort();
这在处理 防抖 和 组件卸载时清理请求 时非常有用。
- 支持并发请求
axios.all([
axios.get('/user'),
axios.get('/posts')
]).then(axios.spread((user, posts) => {
console.log(user.data, posts.data);
}));
Axios 允许多个 HTTP 请求 并行执行,然后合并结果。
- 总结
Axios 是 HTTP 客户端,因为:
-
它的核心功能是发送 HTTP 请求(如 GET、POST)。
-
它基于 HTTP 协议,支持 HTTP 头部、状态码、跨域等特性。
-
它封装了底层 HTTP 请求逻辑,在浏览器用 XMLHttpRequest,在 Node.js 用 http 模块。
-
它提供了完整的 HTTP 请求生命周期管理(拦截、超时、错误处理等)。
-
它能处理多个 HTTP 请求的并发、取消、自动解析等增强功能。
因此,Axios 是一个 强大、灵活、易用的 HTTP 客户端,让开发者可以更高效地与后端 API 进行交互。