axios拦截器底层实现原理
Axios 的拦截器通过内部的Promise 链实现了对请求和响应的拦截与修改。了解其底层原理需要深入到 Axios 源码中,特别是其请求发起和响应处理的逻辑。
Axios 拦截器实现流程
-
拦截器队列
Axios 在内部维护了两个拦截器队列:request
和response
。当开发者通过interceptors.request.use
或interceptors.response.use
注册拦截器时,拦截器会被存入队列。 -
Promise 链
每次调用 Axios 实例发起请求时,会依次将拦截器队列中的函数(请求/响应拦截器)和实际的请求函数组成一个 Promise 链。 -
执行顺序
- 请求拦截器按注册的顺序执行。
- 响应拦截器按注册的顺序逆序执行。
核心源码分析
以下是 Axios 源码的关键部分,用于理解拦截器的实现。
1. 拦截器管理
Axios 内部的 InterceptorManager
类用于管理拦截器:
function InterceptorManager() {
this.handlers = [];
}
// 注册拦截器
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled, // 成功处理函数
rejected: rejected, // 失败处理函数
});
return this.handlers.length - 1; // 返回拦截器的索引
};
// 移除拦截器
InterceptorManager.prototype.eject = function eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null; // 将对应的拦截器置为 null
}
};
InterceptorManager
的核心功能是管理拦截器的添加和删除,所有的拦截器函数存储在 handlers
数组中。
2. 请求的 Promise 链构建
当调用 axios.request(config)
时,会构建一个基于拦截器的 Promise 链:
Axios.prototype.request = function request(config) {
// 初始化配置
config = config || {};
// 将实际请求函数添加到链末尾
let promise = Promise.resolve(config);
// 构建拦截器链
const chain = [];
// 添加请求拦截器(顺序)
this.interceptors.request.handlers.forEach((interceptor) => {
if (interceptor !== null) {
chain.push(interceptor.fulfilled, interceptor.rejected);
}
});
// 添加实际的请求函数
chain.push(dispatchRequest, undefined);
// 添加响应拦截器(逆序)
this.interceptors.response.handlers.forEach((interceptor) => {
if (interceptor !== null) {
chain.push(interceptor.fulfilled, interceptor.rejected);
}
});
// 执行链条中的每个函数
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
};
在上面的实现中:
dispatchRequest
是 Axios 实际发起网络请求的函数。- 请求拦截器按注册的顺序加入链。
- 响应拦截器按逆序加入链。
- 最终,Promise 链依次执行每个拦截器和请求逻辑。
3. 实际请求的实现
dispatchRequest
负责发起 HTTP 请求并返回响应:
function dispatchRequest(config) {
// 检查是否已取消请求
if (config.cancelToken) {
config.cancelToken.throwIfRequested();
}
// 发起请求
return xhrAdapter(config).then(
(response) => {
return response;
},
(error) => {
return Promise.reject(error);
}
);
}
xhrAdapter
是默认的适配器,用于在浏览器环境中通过 XMLHttpRequest
或 fetch
发起请求。
工作流程总结
-
注册拦截器
开发者通过interceptors.request.use
和interceptors.response.use
向 Axios 的拦截器队列中添加拦截函数。 -
发起请求
调用axios(config)
时,Axios 会根据请求拦截器、实际请求函数和响应拦截器构建一个 Promise 链。 -
执行链条
按以下顺序依次执行:- 请求拦截器:按注册顺序执行。
- 实际的请求函数:发送 HTTP 请求。
- 响应拦截器:按注册顺序逆序执行。
-
返回结果
Promise 链最终返回请求的结果或抛出错误,供调用者处理。
图示说明
请求拦截器1 --> 请求拦截器2 --> dispatchRequest --> 响应拦截器2 --> 响应拦截器1
- 请求拦截器按顺序执行:
请求拦截器1 → 请求拦截器2
- 响应拦截器按逆序执行:
响应拦截器2 → 响应拦截器1
Axios 拦截器的特点
- 链式结构:通过
Promise
链灵活地插入和执行拦截器。 - 易扩展:通过
InterceptorManager
动态注册、移除拦截器。 - 一致性:无论请求还是响应,拦截器均可统一添加逻辑。
通过上述机制,Axios 实现了强大且灵活的拦截器功能,开发者可以轻松扩展请求和响应的处理逻辑。