Axios源码(一)axios实例的创建过程

简介: Axios源码(一)axios实例的创建过程

最近在看之前项目对axios请求进行的二次封装,突然对axios的源码感了兴趣,想学习一下axios源码。本文用于记录笔者学习了一些主要的功能函数之后的总结和收获。


Axios的目录结构



Axios的主要功能在lib这个文件夹下面,我们就先分析一下这个文件下面每个文件是干什么的吧!


image.png


Axios创建



我们知道当我们发送axios请求的时候,可以通过下面两中方式进行发送


// 方式一,通过向axios({})里面传入配置对象
axios({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});
// 方式二,通过axios.get/post/delete...
axios.get('/user?ID=12345')


这说明了axios实例既可以使用函数调用的方式,也可以通过对象身上的属性来调用。我们来看看具体怎么实现。


function createInstance(defaultConfig) {
  var context = new Axios(defaultConfig);
  var instance = bind(Axios.prototype.request, context);
  // Copy axios.prototype to instance
  utils.extend(instance, Axios.prototype, context);
  // Copy context to instance
  utils.extend(instance, context);
  // Factory for creating new instances
  instance.create = function create(instanceConfig) {
    return createInstance(mergeConfig(defaultConfig, instanceConfig));
  };
  return instance;
}
var axios = createInstance(defaults);


我们先来看一下axios.js这个文件中的一段代码,里面有一个createInstance函数,传入的参数的是默认的配置。它主要做了以下方面的事情。

  1. new Axios,创建了axios实例命名为context。下面是Axios中的属性


function Axios(instanceConfig) {
  // 配置
  this.defaults = instanceConfig;
  //拦截器
  this.interceptors = {
    request: new InterceptorManager(),
    response: new InterceptorManager()
  };
}
Axios.prototype.request = function request(configOrUrl, config){
    xxxxxx
}
Axios.prototype.getUri = function getUri(config) {
    xxxxxx
}
// 给Axios原型上添加get/head/options/delete方法
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
  Axios.prototype[method] = function(url, config) {
    return this.request(mergeConfig(config || {}, {
      method: method,
      url: url,
      data: (config || {}).data
    }));
  };
});


这里的bind方法是axios自己封装的,相当于Axios.prototype.request.bind(context),得到的instance是一个函数。现在instance就相当于wrap这个函数,instance执行结果就相当于Axios.prototype.request执行的执行结果。现在我们可以通过instance('./api/...')来发送请求,但是还不能通过instance.get([url])来发送


module.exports = function bind(fn, thisArg) {
  return function wrap() {
    // 这里面的arguments应该是调用instacnce中传入的参数
    var args = new Array(arguments.length);
    for (var i = 0; i < args.length; i++) {
      args[i] = arguments[i];
    }
    return fn.apply(thisArg, args);
  };
};


  1. 然后将axios.prototype上面的方法添加到instance实例上面
  2. 再将context上面的属性(defaults,interceptors)添加到instance上面
  3. 然后再合并默认的配置文件和我们传入的配置文件

综上,当我们var axios = createInstance(defaults);的时候,就会得到一个axios实例,其中的this是指向new Axios()得到的对象,即我们可以调用Axios上的方法。并且,createInstance执行返回的是一个函数,也可以通过函数执行的方式来发起请求。


模拟axios创建过程



 // 首先有一个Axios的构造函数,参数是axios的默认配置
 function Axios(instanceConfig){
    this.defaults = instanceConfig;
    // interceptors是拦截器,我们先给它一个空数组,后面再来实现
    this.interceptors = {
        request:[],
        response:[],
    }
}
// 原型链添加属性和方法
Axios.prototype.request = function(instanceConfig){
    console.log('发送Ajax请求' + instanceConfig.method);
}
Axios.prototype.get = function(instanceConfig){
    return this.request({method:'GET'})       
}
Axios.prototype.post = function(instanceConfig){
    return this.request({method:'POST'})
}
// 声明函数,创建Axios实例
function createInstance(instanceConfig){
    // 实例化了一个Axios对象,但是现在我们只能调用它身上的方法,还不能当成函数调用context({})
    let context = new Axios(instanceConfig);
    //创建请求函数,bind返回的一个新的函数,并将指向改变,axios源码中的bind方法是他们自己是实现的
    // instance是一个函数,可以通过instance({})发请求, 但是还不能使用instance.get()/instace.post()
    let instance = Axios.prototype.request.bind(context)
    // 添加get,post,request方法
    Object.keys(Axios.prototype).forEach((key) => {
        instance[key] = Axios.prototype[key].bind(context)
    })
    // 绑定this.default,this.interceptor
    Object.keys(context).forEach(key => {
        instance[key] = context[key];
    })
    return instance;
}


axios既可以用在浏览器环境,也可以用在node环境,它是通过适配器模式并进行如下判断的


// node环境
console.log(typeof process)
console.log(Object.prototype.toString.call(process))
// 浏览器环境
typeof XMLHttpRequest


收获



  1. 了解了call,apply,bind的区别
  2. 了解了axios的创建过程,为什么既可以通过函数调用的方式也可以通过对象上属性的方式发送请求
目录
相关文章
|
7月前
|
存储 JSON 缓存
【源码共读】axios的46个工具函数
【源码共读】axios的46个工具函数
156 0
|
前端开发
前端学习笔记202307学习笔记第六十一天-axios源码总结2
前端学习笔记202307学习笔记第六十一天-axios源码总结2
67 0
|
前端开发
前端学习笔记202307学习笔记第六十一天-axios源码总结1
前端学习笔记202307学习笔记第六十一天-axios源码总结1
70 0
|
前端开发
前端学习笔记202307学习笔记第六十一天-axios源码总结2
前端学习笔记202307学习笔记第六十一天-axios源码总结2
47 0
|
前端开发
axios的原理以及源码讲解
axios的原理以及源码讲解
118 0
|
前端开发 JavaScript Sentinel
我发现了axios源码工具函数中的一个小bug
最开始我一看很蒙蔽,很多时候自己并不会去写这样的函数,说白了还是自己代码底子不行。可能很多大佬一看就明白了,所以基础很重要,基础很重要,基础很重要。箭头函数算是ES6中新增的。
108 0
|
JSON 缓存 前端开发
Axios入门与源码解析
Axios入门与源码解析
Axios入门与源码解析
|
前端开发
搞明白axios 源码,探究配置、拦截器、适配器等核心功能具体的执行过程(二)
搞明白axios 源码,探究配置、拦截器、适配器等核心功能具体的执行过程(二)
搞明白axios 源码,探究配置、拦截器、适配器等核心功能具体的执行过程(二)
|
JSON JavaScript 数据格式
vue项目axios的使用实例详解
vue项目axios的使用实例详解
853 0
vue项目axios的使用实例详解
|
存储 设计模式 JSON
三步法解析Axios源码
三步法解析Axios源码
三步法解析Axios源码