乐趣区

关于javascript:axios源码六

当初来看 axios 的外围, 构造函数 Axios, 它自身就是一个构造函数, 而后在其原型 prototype 上绑定了一些办法, 拦截器就在 this.interceptors 上

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;
退出移动版