axios原理探索

368 阅读2分钟

一、axios使用中产生的疑惑点

  1. 每次request请求都要执行 axios.create 吗?
  2. axios[request,get,post, ...] 区别在哪里?
  3. Axios.prototype.request方法实现了什么?
  4. interceptors拦截是怎么实现的?

二、项目中使用

我们在项目中使用axios一般都会进行简单的封装,如下代码

// request.js
import axios from 'axios';

let config = {
  baseURL: '',
  responseType: 'json',
  xsrfCookieName: 'XSRF-TOKEN',
  xsrfHeaderName: 'X-XSRF-TOKEN'
};

const service = axios.create(config);

//请求拦截
service.interceptors.request.use(config=>{
    showloading(); //等等其他操作
    
    return config;
},error => {
    // do something with request error
    return Promise.reject(error);
})

service.interceptors.response.use(response => {
    hideloading(); //等等数据转换
    
    return response;
},error => {
    // do something with response error
    return Promise.reject(error);
})

export default service;
// 然后在使用时
import service from 'request.js'

service({
    url: 'url',
    method: 'get',
    params: { ...querys }
})

以上为一个简单的自定义配置get请求的调用。

三、读源码尝试解决问题

1、每次request请求都要执行 axios.create 吗?

QA:现在想想,多个请求一起发送的时候,这个service方法作为axios.create的映射是执行多次么?axios.create方法是怎么执行的呢?

这些问题,我们通过查看axios源码来进行解惑

axios.create是什么?

1.png

axios.create 返回一个 instance 函数,这个函数是经过上下文绑定的 Axios.prototype.request方法;

也就是说我们的请求中

每次 service({...参数})请求都是调用的 axios唯一实例request方法

结论:每次发送request都是 axios唯一实例request方法的调用,不存在每次调用axios.create重新创建axios实例的情况

2. axios[request,get,post, ...] 区别在哪里?

  • 使用方法上,如上图所示

2.png

  • 在axios内部实现上,其实都是对Axios.prototype.request的方法调用

3.png

可以看出,最后Axios[method]各方法都是返回经过merge处理后的request方法

那么作为最本质的request方法到底执行了什么呢?

Axios.prototype.request方法实现了什么?

4.png

这其中最重要的就是请求拦截和响应拦截

interceptors拦截是怎么实现的?

1.在axios.create 中会创建axios实例,创建实例时会在内部创建两个拦截管理器

/**
 * Create a new instance of Axios
 */
function Axios(instanceConfig) {
  this.defaults = instanceConfig;
  this.interceptors = {
    request: new InterceptorManager(),
    response: new InterceptorManager()
  };
}

2.在Axios.prototype.request中,使用拦截器实例给到chain数组

  // Hook up interceptors middleware
  // dispatchRequest是实际发送请求的方法
  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());
  }
  
  return promise;

上边代码我们可以看出, chain数组是请求promise链式调用的关键

屡一下步骤:

  • 创建一个chain数组,数组中保存了dispatchRequest,
  • 把请求拦截器的两个方法放到放到chain的头部
  • 把响应拦截器的两个方法放到chain的尾部
  • 依赖于chain.length每次循环取chain的两个值做为到promise.then的resolve,reject
  • 最后把整个promise链返回,实现promise链式调用

最后:对于axios的其他原理还未探究过深,此次仅作为一次学习记录