axios源码

Posted 杨柳岸残月孤轮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了axios源码相关的知识,希望对你有一定的参考价值。

现在来看axios的核心,构造函数Axios,它本身就是一个构造函数,然后在其原型prototype上绑定了一些方法,拦截器就在this.interceptors上.
拦截器为何可以拦截?因为在发送请求之前,config会先传给request拦截器,处理之后传给dispatchRequest(也就是发送请求的方法),然后返回的结果传给response拦截器,response做出操作后再将结果返回

function Axios(instanceConfig) {
  this.defaults = instanceConfig;
  this.interceptors = {
    request: new InterceptorManager(), // InterceptorManager也是一个构造函数
    response: new InterceptorManager()
  };
}

原型prototype添加了request方法(用来发送请求),getUri方法(用来建立请求的路径),还有就是一些方法的别名,比如axios.get()这种写法,就是在prototype上添加了get方法,所以实例上可以访问的到

源码分析如下

\'use strict\';

var utils = require(\'./../utils\');
var buildURL = require(\'../helpers/buildURL\');
var InterceptorManager = require(\'./InterceptorManager\');
var dispatchRequest = require(\'./dispatchRequest\');
var mergeConfig = require(\'./mergeConfig\');

/**
 * 构造函数Axios
 *
 * @param {Object} instanceConfig 默认配置
 */
function Axios(instanceConfig) {
  this.defaults = instanceConfig;
  this.interceptors = {
    request: new InterceptorManager(), // InterceptorManager也是一个构造函数
    response: new InterceptorManager()
  };
}

/**
 * 分发一个请求
 *
 * @param {Object} config 请求的配置 (跟默认配置合并)
 */
Axios.prototype.request = function request(config) {  //  config就是axios({})中的{}
  /*eslint no-param-reassign:0*/
  // Allow for axios(\'example/url\'[, config]) a la fetch API
  if (typeof config === \'string\') {
    config = arguments[1] || {};
    config.url = arguments[0];
  } else {
    config = config || {};
  }

  config = mergeConfig(this.defaults, config);

  // Set config.method
  if (config.method) {
    config.method = config.method.toLowerCase();
  } else if (this.defaults.method) {
    config.method = this.defaults.method.toLowerCase();
  } else {
    config.method = \'get\';
  }

  // filter out skipped interceptors   过滤拦截器
  var requestInterceptorChain = [];
  var synchronousRequestInterceptors = true;
  // forEach方法在InterceptorManager文件中, 其本质还是utils文件中的forEach方法, 参考axios源码(三)
  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    // interceptor就是this.handler的每个元素, 参见InterceptorManager文件
    if (typeof interceptor.runWhen === \'function\' && interceptor.runWhen(config) === false) {
      return;
    }

    synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;

    requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  var responseInterceptorChain = [];
  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    // 跟上面一样
    responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
  });

  var promise;

  if (!synchronousRequestInterceptors) {
    var chain = [dispatchRequest, undefined];

    Array.prototype.unshift.apply(chain, requestInterceptorChain); // 添加到chain
    chain.concat(responseInterceptorChain); // 一个新的数组

    promise = Promise.resolve(config);
    while (chain.length) {
      promise = promise.then(chain.shift(), chain.shift());
    }

    return promise;
  }


  var newConfig = config;
  while (requestInterceptorChain.length) {
    var onFulfilled = requestInterceptorChain.shift();
    var onRejected = requestInterceptorChain.shift();
    try {
      newConfig = onFulfilled(newConfig);
    } catch (error) {
      onRejected(error);
      break;
    }
  }

  try {
    promise = dispatchRequest(newConfig);
  } catch (error) {
    return Promise.reject(error);
  }

  while (responseInterceptorChain.length) {
    promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());
  }

  return promise;
};

Axios.prototype.getUri = function getUri(config) {
  config = mergeConfig(this.defaults, config);
  return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\\?/, \'\');
};

// Provide aliases for supported request methods  给请求的方法提供一个别名
utils.forEach([\'delete\', \'get\', \'head\', \'options\'], function forEachMethodNoData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, config) {
    return this.request(mergeConfig(config || {}, {
      method: method,
      url: url,
      data: (config || {}).data
    }));
  };
});

utils.forEach([\'post\', \'put\', \'patch\'], function forEachMethodWithData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, data, config) {
    return this.request(mergeConfig(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
});

module.exports = Axios;

以上是关于axios源码的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段14——Vue的axios网络请求封装

axios源码解析

axios源码分析

axios源码深入解读(电子文档)

axios源码深入解读(电子文档)

Android 逆向类加载器 ClassLoader ( 类加载器源码简介 | BaseDexClassLoader | DexClassLoader | PathClassLoader )(代码片段