ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

axios 源码拦截器解析

2022-03-08 10:32:50  阅读:161  来源: 互联网

标签:function axios return response 拦截器 promise config 源码


 查看源码我们发现axios的几种请求方式都是调用request方法,下面一步步分析下。

Axios.prototype.request = function request(configOrUrl, config) {
  /*eslint no-param-reassign:0*/
  // Allow for axios('example/url'[, config]) a la fetch API
  
  if (typeof configOrUrl === 'string') {
      //为了支持axios(url, {config})这种写法
    config = config || {};
    config.url = configOrUrl;
  } else {
       //axios(config)
    config = configOrUrl || {};
  }
    //合并配置
  config = mergeConfig(this.defaults, config);

  // 设置请求方法 默认get方法
  if (config.method) {
    config.method = config.method.toLowerCase();
  } else if (this.defaults.method) {
    config.method = this.defaults.method.toLowerCase();
  } else {
    config.method = 'get';
  }
    //数据类型转换
  var transitional = config.transitional;
   
  if (transitional !== undefined) {
    validator.assertOptions(transitional, {
      silentJSONParsing: validators.transitional(validators.boolean),
      forcedJSONParsing: validators.transitional(validators.boolean),
      clarifyTimeoutError: validators.transitional(validators.boolean)
    }, false);
  }
  // 拦截器      
  var requestInterceptorChain = [];  
  var synchronousRequestInterceptors = true;
   //遍历所有请求拦截器
  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
       // 对每一个请求拦截器执行以下代码
    if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
      return;     // 如果 runWhen 的结果是 false ,那么不执行这个拦截器
    }
     // 判断异步同步
    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);
  
    // 添加了拦截器后的chain数组大概会是这样的:
    // [
    //   requestFulfilledFn2, requestRejectedFn2,requestFulfilledFn1, requestRejectedFn1..., 
    //   dispatchRequest, undefined,
    //   responseFulfilledFn1, responseRejectedFn1, responseFulfilledFn2, responseRejectedFn2....,
    // ]
    //初始化化一个promise,给个resolve状态
    promise = Promise.resolve(config);
    while (chain.length) {
              promise = promise.then(chain.shift(), chain.shift());
    }

    return promise;

    // 每次执行while循环,从chain数组里按序取出两项,并分别作为promise.then方法的第一个和第二个参数
    // 按照我们使用InterceptorManager.prototype.use添加拦截器的规则,正好每次添加的就是我们通过InterceptorManager.prototype.use方法添加的成功和失败回调       
     // 第一个请求拦截器的fulfilled函数会接收到promise对象初始化时传入的config对象,而请求拦截器又规定用户写的fulfilled函数必须返回一个config对象,所以通过promise实现链式调用时,每个请求拦截器的fulfilled函数都会接收到一个config对象
    
    // 第一个响应拦截器的fulfilled函数会接受到dispatchRequest请求到的数据(也就是response对象),而响应拦截器又规定用户写的fulfilled函数必须返回一个response对象,所以通过promise实现链式调用时,每个响应拦截器的fulfilled函数都会接收到一个response对象
    
    //通过不断调用promise.then方法形成一个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 请求 是按照请求拦截 请求  响应拦截器顺序执行的。

 axios.interceptors.request.use(function request1(config){
     console.log("request1---success")
     return  config
 },function requesterr1(config){
     console.log("request1----error")
     return  config
 })
 
 axios.interceptors.request.use(function request2(config){
      console.log("request2---success")
      return  config
 },function  requesterr2(config){
      console.log("request2----error")
     return  config
 })
 

 axios.interceptors.response.use(function  response1(response){
      console.log("response1---success")
      return  response
 },function responseerr1(response){
      console.log("response1----error")
     return  response
 })
 
 axios.interceptors.response.use(function response2(response){
      console.log("response2---success")
      return  response
 },function responseerr2(response){
      console.log("response2----error")
      return  response
        
 })

 

标签:function,axios,return,response,拦截器,promise,config,源码
来源: https://www.cnblogs.com/hardmeng/p/15935231.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有