什么是axios
Axios 是一个基于 Promise 的 HTTP 客户端,可以用于浏览器和 Node.js 中。通过 Axios,我们可以在浏览器中发送 XMLHttpRequests,在 Node.js 中发送 http 请求。在某些情况下,我们可能需要拦截请求或响应,以便在请求发送或响应返回之前对其进行处理。这就是 Axios 适配器的作用。
拦截器 Interceptors
定义:在发起请求或做出响应前对请求进行拦截。
javascript
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
还可以给axios的实例添加自定义拦截器
php
const instance = axios.create();
instance.interceptors.request.use(function () {/*...*/});
通常地,我们可以在拦截器里加上一些自己的通用处理逻辑, 比如:
- 请求参数整合,转换
- 添加自定义headers
- 去掉无用参数
- 根据业务返回码处理响应体
- 统一处理每个请求的请求异常和响应异常
- ....
适配器 Adapter
适配器允许用户自定义处理请求
它的配置项是在请求配置里的adapter里,它需要返回一个promise
javascript
// 返回一个 promise 并提供一个有效的响应 (参见 lib/adapters/README.md)。
adapter: function (config) {
/* ... */
return Promise
},
如果用户没有给axios或者axios的实例配置适配器,那么它将使用它默认的适配器

从源码可以看出来,每次请求都会先经过适配器,适配器会返回一个promsie,然后再真正的读取适配器发起的请求得到真正的请求结果
那么可以得出,拦截器与适配器的一些区别了。
拦截器与适配器的区别
- 针对单个请求,拦截器可以配置多个拦截,但是适配器只能配置一个
- 拦截器无法真正拦截请求的发起和返回,但是适配器可以直接拦截请求的发起,直到满足某些条件才真正发起请求
- ...
使用适配器执行阻塞请求
首先在axios的适配器里面配置一个拦截器
typescript
axios.create({
baseURL,
timeout,
headers,
adapter: config => {
return requestEnhancer(config) as Promise<any>;
}
})
适配器对请求进行拦截
javascript
function requestEnhancer(config: AxiosRequestConfig) {
// 需要获取axios.defaults.adapter因为这个适配器是axios底层实现
const adapter = axios.defaults.adapter as AxiosAdapter;
// 此处模拟需要获得ticket才可以没有满足的条件统一进入等待处理
let hasTicket = false;
const whiteList = ['/getTicket']
const request = (myConfig?: AxiosRequestConfig) => {
// 如果ticket是依赖后端处理的话,此处还需要配置一个请求白名单去获取ticket
// 否则获取ticket的请求将永远发不出去,一直等待get-ticket的返回
if (hasTicket || whiteList.includes(myConfig.url)) {
return adapter(config)
} else {
// 通过发布订阅模式监听ticket的返回
bus.on('get-ticket', (ticket) => {
// 可以重新配置axiosConfig,由于此处是等待某个字段满足请求
// 一旦字段满足了请求就需要再调一次request方法使其真正调用adapter发起请求并进行处理
// 此处就可以将ticket放到请求头
// myConfig.headers['ticket'] = ticket
request(myConfig);
})
}
};
return request(config);
}
这样处理后,如果前置字段ticket没有值的时候,接口永远不能发起请求,必须要等待ticket有值返回后,后续接口才能真正发起请求,如此便实现了阻塞请求。
总结
相比于拦截器,适配器能真正的阻塞请求的发起和响应,并且对于前置字段依赖的处理更加优雅,如果涌拦截器去处理前置字段依赖,那么在拦截器去处理的话,那么就可能会对该前置字段进行了多次的冗余处理,比如上述的ticket是依赖接口返回的话,写在拦截器就可能会发起多次请求,造成请求浪费。