持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情aaaaaa
核心--构造函数 Axios
在上面的axios.js的文件中
这一步是非常关键的,其中出现了很多次的 Axios。同时这也是 axios的关键所在
Axios构造函数
Axios文件中主要内容在这个Axios构造函数的构建。
里面包括了
- 调用
axios('url',config),axios({config})的配置方式 - 默认配置和传入配置的合并
- 请求方法的设置
- 请求头配置
- 拦截器注册
- 拦截器操作的promise
- 将
get,post,delete等方法绑定到实例的原型上 - 暴露处Axios
这些内容,如果把这些内容掌握了axios就差不多了
配置对象config的处理
无论是直接通过axios('url',{config})的方法调用 axios 还是 axios({config}) 或者是 axios.get()的方式使用axios , 都绕不过config的配置
直接调用axios({})或者axios("url",{})
使用这两种方式时,原理上就是直接调用Axios的request方法
这时会对调用时,传入的参数进行判断,
如果第一个参数是字符串形式 即用 axios("url",{})的方法,就会将第一个参数中的 url 复制到 第二个参数的config中
如果第一个字符串不存在 即用 axios({})的方式,就将第一个参数的值,直接给了config,
之后还要将传入配置和axios默认配置进行合并。
通过 axios.get()调用
Axios的原型中绑定了一些列的请求方法,调用这些方法会返回一个 this.request同样也是执行请求,会将调用时传入的一系列参数都合并起来,组成一个 config对象
mergeConfig.js
mergeConfig中有争对不同的配置型,确定合并的方式,有一个Map的映射表,还有处理的forEach
将所有的配置文件(用户传入的,默认配置的等等)进行一个合并,最终返回合并后的结果
request()
在Axios.js中,Axios构造函数中的 request()时最重要的模块,下面是我对源码详细注释后的 request实力函数
request(configOrUrl, config) {
/*eslint no-param-reassign:0*/
// Allow for axios('example/url'[, config]) a la fetch API
// 对url的设置,争对调用axios时是否将 url 分出去,做出区分配置
if (typeof configOrUrl === 'string') {
config = config || {};
config.url = configOrUrl;
} else {
config = configOrUrl || {};
}
//将传入的配置和默认配置合并
// mergeConfig 会将参数中的配置合并在一起,
config = mergeConfig(this.defaults, config);
const 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);
}
// Set config.method
// 确定 config 中的方法名
config.method = (config.method || this.defaults.method || 'get').toLowerCase();
// 下面的这堆都是对header进行处理,最后生成请求用的headers
// Flatten headers
const defaultHeaders = config.headers && utils.merge(
config.headers.common,
config.headers[config.method]
);
defaultHeaders && utils.forEach(
['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
function cleanHeaderConfig(method) {
delete config.headers[method];
}
);
config.headers = new AxiosHeaders(config.headers, defaultHeaders);
// filter out skipped interceptors
const requestInterceptorChain = [];
// 同步请求拦截器
let synchronousRequestInterceptors = true;
// 这里的 forEach 不是数组的forEach方法,而是 request 创建的实例 InterceptorManager 中的 实例方法forEach,
// 遍历的是其中的实例属性 handlers数组。下面的响应拦截器也是一样的
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
// 如果用户没有特殊的进行配置的话这里一般不会执行
if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
return;
}
// interceptor.synchronous 是用户 通过 axios.interceptors.request.use 注册时填入的第三个参数 option中的 synchronous 值,一般默认为false
// 表示不是同步全球拦截器
synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
// 在这里将 请求拦截器的内容添加到 chrequestInterceptorChain 中,一组一组的添加
// 请求拦截器的添加是通过 unshift 添加到 chain 的前面的
// 由于这种unshift的方法,后注册的请求拦截器会 比 先注册的拦截器的执行快
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
});
const responseInterceptorChain = [];
// 在这里将 响应拦截器的内容添加到 responseInterceptorChain 中,一组一组的添加
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
// 这里也是将 response 中的内容全部添加到 chain 的后面
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
});
let promise;
let i = 0;
let len;
// 这里的 synchronousRequestInterceptors 同步请求拦截器 一般指都为 false,然后执行里面的内容
if (!synchronousRequestInterceptors) {
// 先把 chain 初始化,第一个是请求,第二个是undefined
const chain = [dispatchRequest.bind(this), undefined];
// 然后在前面添加 请求拦截器的 reject和resolve
chain.unshift.apply(chain, requestInterceptorChain);
// 然后在后面添加 请求拦截器的 reject和resolve
chain.push.apply(chain, responseInterceptorChain);
len = chain.length;
// 创建一个成功的 promise 并把 合并好的config 作为参数传给.then的成功回调
// 这个config 参数就是 给到所有拦截器的config参数
promise = Promise.resolve(config);
while (i < len) {
// 最后再把这些内容 依次调用.then执行,
// 把 chain中的内容, 一组一组的(拦截器的成功回调和失败回调为一组),添加到.then的 resolve函数和reject函数中
promise = promise.then(chain[i++], chain[i++]);
}
// 最终返回一个这个promise对象
return promise;
}
// 从这里往下就是设置的是 synchronousRequestInterceptors 为true时执行的内容
// 会以同步的方式执行拦截器,而不是 .then 后放入异步队列
len = requestInterceptorChain.length;
let newConfig = config;
i = 0;
while (i < len) {
const onFulfilled = requestInterceptorChain[i++];
const onRejected = requestInterceptorChain[i++];
try {
newConfig = onFulfilled(newConfig);
} catch (error) {
onRejected.call(this, error);
break;
}
}
///
try {
//dispatchRequest
promise = dispatchRequest.call(this, newConfig);
} catch (error) {
return Promise.reject(error);
}
i = 0;
len = responseInterceptorChain.length;
while (i < len) {
promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]);
}
return promise;
}
我们将如上的内容解读完后,了解到这一步中就是形成了一个 promise链,其中的 dispatchRequest 才是请求的更深层。