在上一篇文章中分析了axios的实例创建实际上所有aixos请求的创建都是request方法来实现的。
在实际分析之前,先来梳理总结下axios创建请求的方式:
axios(config)
axios(url, config)
axios.create(config)
axios.request(config)
axios.get(url, config)
同理:delete,head, options与get相同
axios.post(url, data, config)
同理:put, patch与post相同
实际上,axios把Axios暴露出去了,你也可以同Axios来创建axios实例对象,调用request、get等定义在Axios原型上方法
上面就是axios所有请求支持,实际上上面所有请求都是调用request方法来实现的,而request方法是在core/Axios.js中定义的
本篇文章分析Axios.js模块的实现功能,实际上Axios.js实现的功能主要是两块:
Axios实例创建、Axios.prototype.request方法定义、get等具体请求定义
请求拦截器处理
Axios构造函数中,创建两个实例属性,分别是defaults、interceptors
defaults表示配置对象,如果不是用户直接调用Axios,那这个属性值就是defaults.js模块暴露的默认值
interceptors:拦截器,定义了request和response拦截器属性分别表示请求和响应拦截器
this.interceptors = { // InterceptorManager就是拦截器对象构造函数 request: new InterceptorManager(), response: new InterceptorManager() };
该方法是axios项目的核心处理方法,实现用户自定义配置、应用拦截器、发送请求核心功能
// 支持axios(url, config)
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';
梳理拦截器位置
// chain是一个数组,dispatchRequest是发送请求模块
var chain = [dispatchRequest, undefined];
// 请求拦截器处理
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);
});
实际上上面有个小技巧,就是通过chain数组模拟堆栈顺序,请求拦截器在发送请求前,响应拦截器在请求成功后,而实现这个效果就是通过数组的顺序来实现的,故:
request调用unshift将拦截器插入最前部
response调用push将拦截器推入尾部
发起请求并处理拦截器
var promise = Promise.resolve(config);
while(chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
实际上上面会形成链式,下一次promise依赖上一次promise的返回值
实例:
假设定义一个请求拦截器和一个响应拦截器
//添加请求拦截器
axios.interceptors.request.use(function(config){
return config;
},function(error){
//请求错误时做些事
return Promise.reject(error);
});
//添加响应拦截器
axios.interceptors.response.use(function(response){
return response;
},function(error){
//请求错误时做些事
return Promise.reject(error);
});
此时再来看chain,实际上会有如下元素:
[requestResolveFn, requestRejectFn, dispatchRequest, undefined, responseResolveFn, responseRejectFn]
再执行上面的循环:
- 第一次Promise总是resolve, 所以执行requestResoveFn
- requestResoveFn返回结果是resolve,所以dispatchRequest
- dispatchRequest是发送请求的模块,若reslove则调用responseResolveFn,若reject,则responseRejectFn
request中需要关注的点有两个:
请求和响应拦截器的位置的处理
while循环处理promise的链式
下一篇文章将分析dispatchRequest模块的实现逻辑(这是发送请求的模块)。