axios.js源码入口文件
module.exports = axios;
// Allow use of default import syntax in TypeScript
module.exports.default = axios;
这里可以看出导出了axios,支持两种导入的形式
import axios from 'axios'
import { axios } from 'axios'
那么导出的axios本质是什么呢? 答案是一个函数
//调用了一个createInstance函数
var axios = createInstance(defaults);
//createInstance函数
function createInstance(defaultConfig) {
//Axios构造函数实例化一个对象
var context = new Axios(defaultConfig);
//bind函数是一个bind.js文件中导出的一个函数,利用了闭包的特性
//调用Axios构造函数的request方法,把this指向实例context,然后返回一个函数
//在下面的bind.js有着完整bind函数的源码
var instance = bind(Axios.prototype.request, context);
//instance函数继承Axios.prototype 和 创建出来的实例
// Copy axios.prototype to instance
utils.extend(instance, Axios.prototype, context);
// Copy context to instance
utils.extend(instance, context);
//导出instance函数
return instance;
}
所以,从上面的分析,我们可以从本质上知道axios是一个函数,所以在使用的时候,形式如下:
axios({
url: '',
method: ''
})
那么又有疑问?axios不是还有对象形式的写法吗?
axios.get()
axios.post()
//这又是上面原理呢?
函数也是对象,所以可以添加一个属性,指向Axios构造函数
axios.Axios = Axios;
//那么这里,我们就需要看Axios的构造函数了
Axios构造函数的部分源码
function Axios(instanceConfig) {
//赋值默认配置
this.defaults = instanceConfig;
//拦截器
this.interceptors = {
request: new InterceptorManager(),
response: new InterceptorManager()
};
}
Axios原型上的request方法
Axios.prototype.request = function request(config) {
//支持字符串和对象两种形式
if (typeof config === 'string') {
config = arguments[1] || {};
config.url = arguments[0];
} else {
config = config || {};
}
//把自己的配置和默认的配置合并
config = mergeConfig(this.defaults, config);
//检查method,如果没有传,默认是get
if (config.method) {
config.method = config.method.toLowerCase();
} else if (this.defaults.method) {
config.method = this.defaults.method.toLowerCase();
} else {
config.method = 'get';
}
// Hook up interceptors middleware
//chain是一个数组,存放发送请求模块的
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);
});
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
//然后返回一个promise对象
return promise;
};
Axios原型上添加各种请求方式
//循环字符串,然后分别添加在原型上
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
Axios.prototype[method] = function(url, config) {
//调用了内部的request方法, 合并配置
return this.request(mergeConfig(config || {}, {
method: method,
url: url,
data: (config || {}).data
}));
};
});
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
Axios.prototype[method] = function(url, data, config) {
return this.request(mergeConfig(config || {}, {
method: method,
url: url,
data: data
}));
};
})
结论
就从上给Axios的原型上添加各种请求属性,我们就可以知道了axios.get()等等是怎么回事了
axios是一个函数,继承了Axios,就可以使用原型上的各种方法了
当我们也应该知道,无论我们使用哪种方法,都是调用了request方法
额外补充
//bind.js源码
module.exports = function bind(fn, thisArg) {
return function wrap() {
var args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
//返回一个fn函数,把this指向thisArg, 传递循环出来的参数
return fn.apply(thisArg, args);
};
};
以上有错误,请指正,谢谢。