Axios Interceptor - Promise Chaining
日常用烂的工具居然也能看出点新玩意
Axios Interceptor Example
在创建 axios 实例时,axios 会初始化一个名为 interceptors
的对象,其中包含了两个属性:request
和 response
。这两个属性分别对应了一个数组,用于存储请求拦截器和响应拦截器。当我们添加一个拦截器时,实际上就是将该拦截器的回调函数放入对应数组的末尾。
import axios from "axios";
// 创建 axios 实例
const instance = axios.create({
baseURL: "<https://api.example.com>",
timeout: 10000,
});
// 添加请求拦截器
instance.interceptors.request.use(requestHandler, errorHandler);
// 添加响应拦截器
instance.interceptors.response.use(responseHandler, errorHandler);
Axios Request Dispatcher
function dispatchRequest(config) {
// 默认的处理函数
// 此处故意放置了两个元素
// 第一个元素代表 axios 实际请求的 fulfill
// 第二个元素代表 axios 实际请求的 reject, 这里设置为 undefined, 代表不处理
var chain = [dispatchRequestAjax, undefined];
// 创建包含config的Promise对象
var promise = Promise.resolve(config);
// 将所有请求拦截器的回调函数添加到chain数组的最前面
this.interceptors.request.forEach(function unshiftRequestInterceptors(
interceptor
) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});
// 将所有响应拦截器的回调函数添加到chain数组的最后面
this.interceptors.response.forEach(function pushResponseInterceptors(
interceptor
) {
chain.push(interceptor.fulfilled, interceptor.rejected);
});
/*
如果同时存在请求拦截器和响应拦截器
那么最终构成的chain数组的结构如下
注意顺序
[
...(multiple request interceptors),
requestFullfil_2, requestReject_2,
requestFullfil_1, requestReject_1,
dispatchRequestAjax, undefined, // 一开始默认添加的处理函数
responseFullfil_1, responseReject_1,
responseFullfil_2, responseReject_2,
...(multiple response interceptors)
]
*/
// 通过reduce方法将所有回调函数串联起来执行
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
// 返回处理后的结果
return promise;
}
这一段最经典的地方在于:
-
其中最经典的地方在于
while (chain.length)
这一行代码,通过循环取出chain
数组中的回调函数,实现了链式调用的本质。 -
这段代码实现了 promise 的链式调用。
Promise.then
方法接受两个参数,分别是onFulfilled
和onRejected
- 每次取出两个元素(代表成功回调和失败回调)作为
then
方法的参数,然后将返回的 Promise 对象赋值给promise
,最终返回处理后的promise
对象。
-
这样做的好处是可以将多个回调函数按照一定的顺序执行,实现拦截器的链式调用,方便我们对请求和响应进行处理和管理。
-
假设有如下数个拦截器:
[ requestFullfil_2, requestReject_2, requestFullfil_1, requestReject_1, dispatchRequestAjax, undefined, // 一开始默认添加的处理函数 responseFullfil_1, responseReject_1, responseFullfil_2, responseReject_2, ]
-
其中如果完全resolve, 则执行顺序为:
- requestFullfil_2
- requestFullfil_1
- dispatchRequestAjax
- responseFullfil_1
- responseFullfil_2
-
假设 requestFullfil_2 reject, 则执行顺序为:
- requestFullfil_2(fail) + requestReject_2
- requestReject_1
- undefined, 等于当前 promise 没有 onReject事件, 继续 reject
- requestReject_1
- requestReject_2
-