阅读axios的源码

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);
  };
};

以上有错误,请指正,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值