查看源码我们发现axios的几种请求方式都是调用request方法,下面一步步分析下。
Axios.prototype.request = function request(configOrUrl, config) {
/*eslint no-param-reassign:0*/
// Allow for axios('example/url'[, config]) a la fetch API
if (typeof configOrUrl === 'string') {
//为了支持axios(url, {config})这种写法
config = config || {};
config.url = configOrUrl;
} else {
//axios(config)
config = configOrUrl || {};
}
//合并配置
config = mergeConfig(this.defaults, config);
// 设置请求方法 默认get方法
if (config.method) {
config.method = config.method.toLowerCase();
} else if (this.defaults.method) {
config.method = this.defaults.method.toLowerCase();
} else {
config.method = 'get';
}
//数据类型转换
var transitional = config.transitional;
if (transitional !== undefined) {
validator.assertOptions(transitional, {
silentJSONParsing: validators.transitional(validators.boolean),
forcedJSONParsing: validators.transitional(validators.boolean),
clarifyTimeoutError: validators.transitional(validators.boolean)
}, false);
}
// 拦截器
var requestInterceptorChain = [];
var synchronousRequestInterceptors = true;
//遍历所有请求拦截器
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
// 对每一个请求拦截器执行以下代码
if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
return; // 如果 runWhen 的结果是 false ,那么不执行这个拦截器
}
// 判断异步同步
synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
//头部添加, 先加入后执行
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
});
var responseInterceptorChain = [];
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
// 先加入的先执行
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
});
var promise;
// 如果拦截器是异步执行
if (!synchronousRequestInterceptors) {
// 初始化一个执行链
var chain = [dispatchRequest, undefined];
// 把请求拦截器放在链首
Array.prototype.unshift.apply(chain, requestInterceptorChain);
// 把响应拦截器放在链尾
chain = chain.concat(responseInterceptorChain);
// 添加了拦截器后的chain数组大概会是这样的:
// [
// requestFulfilledFn2, requestRejectedFn2,requestFulfilledFn1, requestRejectedFn1...,
// dispatchRequest, undefined,
// responseFulfilledFn1, responseRejectedFn1, responseFulfilledFn2, responseRejectedFn2....,
// ]
//初始化化一个promise,给个resolve状态
promise = Promise.resolve(config);
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
// 每次执行while循环,从chain数组里按序取出两项,并分别作为promise.then方法的第一个和第二个参数
// 按照我们使用InterceptorManager.prototype.use添加拦截器的规则,正好每次添加的就是我们通过InterceptorManager.prototype.use方法添加的成功和失败回调
// 第一个请求拦截器的fulfilled函数会接收到promise对象初始化时传入的config对象,而请求拦截器又规定用户写的fulfilled函数必须返回一个config对象,所以通过promise实现链式调用时,每个请求拦截器的fulfilled函数都会接收到一个config对象
// 第一个响应拦截器的fulfilled函数会接受到dispatchRequest请求到的数据(也就是response对象),而响应拦截器又规定用户写的fulfilled函数必须返回一个response对象,所以通过promise实现链式调用时,每个响应拦截器的fulfilled函数都会接收到一个response对象
//通过不断调用promise.then方法形成一个promise链,从而将所有的任务执行串联起来。
}
//如果是同步 按照顺序 先指行请求拦截器 再执行 请求操作 请求结果后再执行 响应拦截器
var newConfig = config;
while (requestInterceptorChain.length) {
var onFulfilled = requestInterceptorChain.shift();
var onRejected = requestInterceptorChain.shift();
try {
newConfig = onFulfilled(newConfig);
} catch (error) {
onRejected(error);
break;
}
}
try {
promise = dispatchRequest(newConfig);
} catch (error) {
return Promise.reject(error);
}
while (responseInterceptorChain.length) {
promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());
}
return promise;
};
手动添加几个请求拦截器和响应拦截器 可以更好的理解为什么axios 请求 是按照请求拦截 请求 响应拦截器顺序执行的。
axios.interceptors.request.use(function request1(config){
console.log("request1---success")
return config
},function requesterr1(config){
console.log("request1----error")
return config
})
axios.interceptors.request.use(function request2(config){
console.log("request2---success")
return config
},function requesterr2(config){
console.log("request2----error")
return config
})
axios.interceptors.response.use(function response1(response){
console.log("response1---success")
return response
},function responseerr1(response){
console.log("response1----error")
return response
})
axios.interceptors.response.use(function response2(response){
console.log("response2---success")
return response
},function responseerr2(response){
console.log("response2----error")
return response
})