axios拦截器执行顺序的源码解释
我们先来看一段代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.20.0-0/axios.min.js"></script>
<script>
//添加请求拦截器(回调函数)
axios.interceptors.request.use(
config => {
console.log('request interceptor1 onResolved()')
return config
},
error => {
console.log('request interceptor1 onRejected()')
return Promise.reject(error)
}
)
axios.interceptors.request.use(
config => {
console.log('request interceptor2 onResolved()')
return config
},
error => {
console.log('request interceptor2 onRejected()')
return Promise.reject(error)
}
)
//添加响应拦截器
axios.interceptors.response.use(
response => {
console.log('response interceptor1 onResolved()')
return response
},
error => {
console.log('response interceptor1 onRejected()')
return Promise.reject(error)
}
)
axios.interceptors.response.use(
response => {
console.log('response interceptor2 onResolved()')
return response
},
error => {
console.log('response interceptor2 onRejected()')
return Promise.reject(error)
}
)
axios.get('http://localhost:3000/posts')
.then(response => {
console.log('data', response.data);
})
.catch(error => {
console.log('error', error.message)
})
</script>
</body>
</html>
通过运行这段程序,我们可以在控制台看到分别打印的是:
request interceptor2 onResolved()
request interceptor1 onResolved()
response interceptor1 onResolved()
response interceptor2 onResolved()
data
那么为什么会出现这样的结果吗?通过查看axios的源码,我知道了答案,下面分享给大家
我摘取源码中关于这个的部分进行解释:
Axios.prototype.request = function request(config) {
/*eslint no-param-reassign:0*/
// Allow for axios('example/url'[, config]) a la fetch API
if (typeof config === 'string') {
config = arguments[1] || {};
config.url = arguments[0];
} else {
config = config || {};
}
// 合并配置
config = mergeConfig(this.defaults, config);
// 添加method配置, 默认为get
config.method = config.method ? config.method.toLowerCase() : 'get';
/*
创建用于保存请求/响应拦截函数的数组
数组的中间放发送请求的函数
数组的左边放请求拦截器函数(成功/失败)
数组的右边放响应拦截器函数
*/
var chain = [dispatchRequest, undefined];
var promise = Promise.resolve(config);
// 后添加的请求拦截器保存在数组的前面
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});
// 后添加的响应拦截器保存在数组的后面
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
chain.push(interceptor.fulfilled, interceptor.rejected);
});
// 通过promise的then()串连起所有的请求拦截器/请求方法/响应拦截器
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
// 返回用来指定我们的onResolved和onRejected的promise
return promise;
};
这个request方法就是axios发送请求的核心方法,在源码中将发送请求分为了几个部分(请求拦截器,发送请求,响应拦截器,响应回调),通过Promise的链式调用将这些部分有机地结合了起来,这样就构成了发送请求拿到数据处理的全部过程。
下面我们一一分析:
- 代码开始构建了一个config配置对象,用于第一次执行Promise返回一个成功的promise
- 最核心的数组chain,这个数据中保存了请求拦截器函数,响应拦截器函数和默认就有的发送请求的函数,第一步返回的成功的promise对象,将遍历这个数组逐一执行里面的函数,并返回新的Promise对象
- 往数组中添加请求拦截器函数,依照axios请求的执行顺序,请求拦截器应该在发送请求之前执行,故应该添加在发送请求函数的前面,所以使用的是数组的unshift方法,这个方法意思是头部添加,即后面添加的元素总是在头部
- 往数组中添加请求拦截器函数,依照axios请求的执行顺序,响应拦截器应该在发送请求之后执行,故应该添加在发送请求函数的后面,所以使用的是数组的push方法,这个方法意思是尾部添加,即后面添加的元素总是在尾部
- promise遍历执行,使用的while循序,使用数组的shift方法每次从中取出两个函数执行(成功回调,失败回调)
- 返回Promise对象,用于执行我们指定的响应数据的回调
相信我说到这里,大家就已经懂了,不要需要伙伴们对Promise有一定的理解,不懂的小伙伴可以先看看Promise是什么
下面,我把图给大家看一看:

其中,还有一些细枝末节的地方我没讲,因为我也不懂,我只知道它大概是这么个执行流程,我能理解的都讲了,望大家采纳!
本文深入剖析了Axios库的请求流程,详细解读了请求和响应拦截器的执行顺序及其实现原理,揭示了Promise链如何串联整个请求过程。

2806

被折叠的 条评论
为什么被折叠?



