Skip to content
js
class Axios {
  constructor(instanceConfig) {
    this.defaults = instanceConfig;
    this.interceptors = {
      request: new InterceptorManager(),
      response: new InterceptorManager()
    };
  }

  request(configOrUrl, config) {
    if (typeof configOrUrl === 'string') {
      config = config || {};
      config.url = configOrUrl;
    } else {
      config = configOrUrl || {};
    }
    config = mergeConfig(this.defaults, config);
    const {transitional, paramsSerializer, headers} = config;
    if (transitional !== undefined) {
      validator.assertOptions(transitional, {
        silentJSONParsing: validators.transitional(validators.boolean),
        forcedJSONParsing: validators.transitional(validators.boolean),
        clarifyTimeoutError: validators.transitional(validators.boolean)
      }, false);
    }

    // 更高版本的 axios 将针对config.params 的 paramsSerializer 视作对象,支持 encode 和 serialize 方法
    if (paramsSerializer !== undefined) {
      validator.assertOptions(paramsSerializer, {
        encode: validators.function,
        serialize: validators.function
      }, true);
    }
    config.method = (config.method || this.defaults.method || 'get').toLowerCase();
    let contextHeaders;
    contextHeaders = headers && utils.merge(
      headers.common,
      headers[config.method]
    );
    contextHeaders && utils.forEach(
      ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
      (method) => {
        delete headers[method];
      }
    );
    config.headers = AxiosHeaders.concat(contextHeaders, headers);

    // 请求拦截器从数组头部推入
    const requestInterceptorChain = [];
    let synchronousRequestInterceptors = true;
    // 注意:这里拦截器的遍历使用的是其原型上的forEach方法(会过滤null项)
    this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
      if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
        return;
      }
      // 所有请求拦截器的synchronous都设置为true时,才会触发同步执行机制
      synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
      requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
    });

    // 响应拦截器 从数组尾部推入
    const responseInterceptorChain = [];
    this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
      responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
    });

    let promise;
    let i = 0;
    let len;

    // 请求拦截器 异步的场景,全部按照promise链执行
    if (!synchronousRequestInterceptors) {
      // 此处只是bind绑定dispatchRequest的this指向,dispatchRequest并没有执行
      const chain = [dispatchRequest.bind(this), undefined];
      chain.unshift.apply(chain, requestInterceptorChain);
      chain.push.apply(chain, responseInterceptorChain);
      /*
        执行到这里,整个chain的形式是这样的:
        [requestResolve, requestReject, ..., dispatchResolve, dispatchReject, responseResolve, responseReject, ...]
      */
      len = chain.length;
      promise = Promise.resolve(config);
      while (i < len) {
        promise = promise.then(chain[i++], chain[i++]);
      }
      return promise;
    }

    // 请求拦截器 同步
    len = requestInterceptorChain.length;
    let newConfig = config;
    i = 0;
    while (i < len) {
      const onFulfilled = requestInterceptorChain[i++];
      const onRejected = requestInterceptorChain[i++];
      try {
        newConfig = onFulfilled(newConfig);
      } catch (error) {
        onRejected.call(this, error);
        break;
      }
    }

    // dispatchRequest和响应拦截器 依旧是promise.then微任务
    try {
      // 此处利用call执行dispatchRequest,返回的是promise
      promise = dispatchRequest.call(this, newConfig);
    } catch (error) {
      return Promise.reject(error);
    }
    i = 0;
    len = responseInterceptorChain.length;
    while (i < len) {
      promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]);
    }
    return promise;
  }
}

Axios class 中的核心在于 request 方法。

request 方法中,主要涉及到了三方面:

  1. 请求拦截器 interceptor-request
  2. 分发请求 dispatchRequest
  3. 响应拦截器 interceptor-response

请求拦截器和响应拦截器的构造函数都是 InterceptorManager

因此需要接着了解下 InterceptorManagerdispatchRequest 这俩方面的实现原理。

TIP

额外说明一下 synchronous 配置项对于请求拦截器的影响:

假设有:

  1. interceptor-request
  2. transform-request
  3. transform-response
  4. interceptor-response
  5. main thread

那么对于 synchronousfalse ,此时会按照 promise 链的顺序来执行,又因为都是 then 微任务,所以执行顺序是 1、2、3、4、5

如果声明 synchronoustrue,请求拦截器会以同步的方式进行。此时 1、2 不会被推到 promise 链中,但 3、4 实际上是 promise 链中,此时执行顺序为 1、2、5、3、4