从零实现axios(3.2小节-实现拦截器2)

43 阅读2分钟

实现拦截器2

InterceptorManager 类的 use 方法,还接收一个options参数,该参数是一个对象类型,包含两个字段:一个是synchronous属性,值是布尔类型;一个是runWhen属性,值是函数类型。

runWhen函数的作用非常简单,就是接收一个合并后的配置对象(config),用户可以在这个函数里面自行决定当前的拦截器是否生效,返回false表示不生效,否则生效。

synchronous属性,用来决定rejected处理函数是同步生效,还是异步生效,默认是异步生效。这么说可能有点难以理解,我画了个图帮助大家理解。

3.2.syn.jpg

我们假设通过多次调用axios.interceptors.request.use函数,添加了多个interceptor对象。那么synchronous=false,决定了rejected处理函数将会异步处理前一个interceptor拦截器里的fulfilled函数抛出的异常。synchronous=true, 决定了rejected处理函数将会同步处理同一个interceptor拦截器里的fulfilled函数抛出的异常。

InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
  this.handlers.push({
    fulfilled: fulfilled,
    rejected: rejected,
    synchronous: options ? options.synchronous : false,
    runWhen: options ? options.runWhen : null
  });
  return this.handlers.length - 1;
};
Axios.prototype.request = function request(config) {
  // ...
  if (config.method) {
    config.method = config.method.toLowerCase();
  } else if (this.defaults.method) {
    config.method = this.defaults.method.toLowerCase();
  } else {
    config.method = "get";
  }

  // 把请求拦截器添加到requestInterceptorChain数组中
  var requestInterceptorChain = [];
  var synchronousRequestInterceptors = true;
  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    // runWhen函数决定当前interceptor是否被应用
    if (
       typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false
    ) {
      return;
    }

    // 用来决定rejected处理函数是同步生效,还是异步生效
    synchronousRequestInterceptors = synchronousRequestInterceptors 
      && interceptor.synchronous;
    requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
  });


  // 把响应拦截器添加到responseInterceptorChain数组中
  var responseInterceptorChain = [];
  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
  });

  var promise;

  // rejected异步生效
  if (!synchronousRequestInterceptors) {
    var chain = [dispatchRequest, undefined];

    // 把请求拦截处理函数添加到chain数组前面去,在dispatchRequest请求发出前进行拦截处理
    Array.prototype.unshift.apply(chain, requestInterceptorChain);
    // 把响应拦截处理函数添加到chain数组前面去,在响应返回前进行拦截处理
    chain = chain.concat(responseInterceptorChain);

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

    return promise;
  }


  // rejected同步生效
  var newConfig = config;
  // 先执行请求拦截器
  while (requestInterceptorChain.length) {
    var onFulfilled = requestInterceptorChain.shift();
    var onRejected = requestInterceptorChain.shift();
    try {
      newConfig = onFulfilled(newConfig);
    } catch (error) {
      onRejected(error);
      break;
    }
  }

  // 开始发出http请求
  try {
    promise = dispatchRequest(newConfig);
  } catch (error) {
    return Promise.reject(error);
  }

  // 执行响应拦截器
  while (responseInterceptorChain.length) {
    promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());
  }

  return promise;
};