【axios】的浅度分析

打印 上一主题 下一主题

主题 807|帖子 807|积分 2421

一、Axios的拦截器醒目些什么?

Axios拦截器的实现原理主要涉及两个方面:请求拦截器和相应拦截器,它们分别在请求发送前和相应返回后举行预处理和后处理。
Axios内部维护了两个数组,一个用于存储请求拦截器,另一个用于存储相应拦截器。每个拦截器都是一个函数,这些函数按照它们在数组中定义的顺序被依次实行。
1、请求拦截器:
   当Axios发起一个请求时,会首先遍历并实行请求拦截器数组中的每个函数。
请求拦截器的作用是在请求发送前对请求举行修改或添加一些公共的逻辑,比方给每个请求体都加上token,或者修改请求的配置,如headers、url、params等。此外,也可以在此阶段取消请求。
请求拦截器的修改或添加的配置将被用于之后的请求发送。
  2、相应拦截器:
   一旦请求被发送并得到相应,Axios会遍历并实行相应拦截器数组中的每个函数。
相应拦截器的作用是在相应返回后对相应举行特定的处理,比方对返回的数据举行同一处理或对特定的错误举行处理。
如果相应是一个正常的相应,可以直接返回数据或对数据举行修改。如果相应是一个错误(比方,404或500状态码),可以举行错误处理或重试逻辑。
  利用Axios拦截器的利益包罗同一处理公共逻辑,减少重复代码,提高代码的可读性和可维护性。同时,也可以在请求或相应不符合预期时举行同一处理,提高步伐的健壮性。
必要留意的是,在利用Axios拦截器时,应确保请求拦截器在相应拦截器之前实行,避免逻辑上的错误。此外,应避免在拦截器中修改原始请求或相应数据,以免影响其他拦截器或请求处理器的处理结果。同时,应思量性能问题,避免在拦截器中举行耗时的操作。
综上所述,Axios拦截器的实现原理主要基于其内部维护的请求和相应拦截器数组,通过依次实行这些拦截器函数,实现对请求和相应的预处理和后处理。
二、Axios 源码中,拦截器是怎么实现的?(最简化的理解)

Axios 的拦截器实现基于 Axios 的核心原理,即 Axios 实例是一个包含请求和相应拦截器堆栈的对象。当发出请求或接收相应时,Axios 会遍历这些拦截器,并按照添加的顺序实行请求拦截器,以及按照相反的顺序实行相应拦截器。
在 Axios 的源码中,拦截器是通过一个 AxiosInterceptorManager 实例来管理的,它维护了一个拦截器数组。每个拦截器都是一个包含 fulfilled 和 rejected 函数的对象。这两个函数分别对应于拦截器成功处理和拦截器处理出错的情况。
以下是 Axios 拦截器管理器的一个简化版本,展示了其核心实现思绪:
  1. class InterceptorManager {
  2.   constructor() {
  3.     this.handlers = []; // 存储拦截器的数组
  4.   }
  5.   use(fulfilled, rejected) {
  6.     this.handlers.push({
  7.       fulfilled: fulfilled,
  8.       rejected: rejected
  9.     });
  10.     return this.handlers.length - 1; // 返回拦截器的ID
  11.   }
  12.   eject(id) {
  13.     if (this.handlers[id]) {
  14.       this.handlers[id] = null; // 移除拦截器
  15.     }
  16.   }
  17.   forEach(fn) {
  18.     this.handlers.forEach((h) => {
  19.       if (h !== null) {
  20.         fn(h);
  21.       }
  22.     });
  23.   }
  24. }
复制代码
在发送请求或接收相应时,Axios 会创建一个 promise 链,并通过 forEach 方法将拦截器中的 fulfilled 和 rejected 函数添加到这个链中。这样,每个拦截器都可以对请求或相应举行处理,然后将结果通报到链的下一个拦截器,或者在出错时竣事链的实行。
PS:留意,上面说的是拦截管理器,并非下面要说的拦截器
  1. axios.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
  2.   chain.unshift(interceptor.fulfilled, interceptor.rejected);
  3. });
  4. axios.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
  5.   chain.push(interceptor.fulfilled, interceptor.rejected);
  6. });
复制代码
在 Axios 的完整实现中,这个拦截器机制被集成到了 Axios 的请求发送和相应处理流程中。通过这种方式,Axios 可以在发送请求之前和接收相应之后,但在用户定义的 .then 或 .catch 实行之前,插入自定义的逻辑。
请留意,这里提供的代码只是为了说明 Axios 拦截器的实现原理,并不是 Axios 源码的完整复制。
三、高度简化的源码(axios拦截器实现源码)

Axios 拦截器的实现源码涉及到其核心模块的设计。Axios 允许你注册请求拦截器和相应拦截器,这些拦截器在请求发送前和相应返回后举行相应的处理。以下是简化的 Axios 拦截器实现源码的概述:
  1. // 假设 Axios 实例有一个 interceptors 对象,其中包含了 request 和 response 两个数组
  2. const instance = {
  3.   interceptors: {
  4.     request: [],
  5.     response: []
  6.   }
  7. };
  8. // 请求拦截器的函数定义
  9. function onFulfilled(fulfilled, rejected) {
  10.   return function (config) {
  11.     return new Promise((resolve, reject) => {
  12.       try {
  13.         const result = fulfilled(config);
  14.         if (result && typeof result.then === 'function') {
  15.           result.then(resolvedConfig => {
  16.             resolve(resolvedConfig);
  17.           }, rejected);
  18.         } else {
  19.           resolve(result);
  20.         }
  21.       } catch (error) {
  22.         reject(error);
  23.       }
  24.     };
  25.   };
  26. }
  27. // 响应拦截器的函数定义
  28. function onFulfilledResponse(fulfilled, rejected) {
  29.   return function (response) {
  30.     return new Promise((resolve, reject) => {
  31.       try {
  32.         const result = fulfilled(response);
  33.         if (result && typeof result.then === 'function') {
  34.           result.then(resolvedResponse => {
  35.             resolve(resolvedResponse);
  36.           }, rejected);
  37.         } else {
  38.           resolve(result);
  39.         }
  40.       } catch (error) {
  41.         reject(error);
  42.       }
  43.     };
  44.   };
  45. }
  46. // 添加请求拦截器
  47. instance.interceptors.request.use = function (fulfilled, rejected) {
  48.   this.interceptors.request.push({
  49.     fulfilled: onFulfilled(fulfilled, rejected),
  50.     rejected: rejected
  51.   });
  52.   return this;
  53. };
  54. // 添加响应拦截器
  55. instance.interceptors.response.use = function (fulfilled, rejected) {
  56.   this.interceptors.response.push({
  57.     fulfilled: onFulfilledResponse(fulfilled, rejected),
  58.     rejected: rejected
  59.   });
  60.   return this;
  61. };
  62. // 简化版的请求发送函数,用于展示拦截器如何处理
  63. function dispatchRequest(config) {
  64.   return new Promise((resolve, reject) => {
  65.     // 遍历并执行请求拦截器
  66.     const chain = [Promise.resolve(config)];
  67.     instance.interceptors.request.forEach(interceptor => {
  68.       chain.unshift(interceptor.fulfilled, interceptor.rejected);
  69.     });
  70.     // 遍历并执行响应拦截器
  71.     chain.push(dispatchRequestToServer); // 假设这个函数是实际发送请求到服务器的函数
  72.     while (chain.length) {
  73.       const currentInterceptor = chain.shift();
  74.       const nextInterceptor = chain.shift();
  75.       if (typeof currentInterceptor === 'function') {
  76.         currentInterceptor(config).then(chain => {
  77.           if (typeof nextInterceptor === 'function') {
  78.             nextInterceptor(chain);
  79.           } else {
  80.             resolve(chain);
  81.           }
  82.         }).catch(reject);
  83.       }
  84.     }
  85.   });
  86. }
  87. // 假设函数,用于实际发送请求到服务器
  88. function dispatchRequestToServer(config) {
  89.   // 这里应该是实际的请求发送逻辑,为了简化,我们直接返回一个模拟的响应
  90.   return Promise.resolve({
  91.     data: 'Response data'
  92.   });
  93. }
  94. // 使用拦截器
  95. instance.interceptors.request.use(
  96.   config => {
  97.     // 在发送请求之前做些什么
  98.     console.log('Request interceptor called', config);
  99.     // 可以在这里修改config对象
  100.     return config;
  101.   },
  102.   error => {
  103.     // 对请求错误做些什么
  104.     return Promise.reject(error);
  105.   }
  106. );
  107. instance.interceptors.response.use(
  108.   response => {
  109.     // 对响应数据做点什么
  110.     console.log('Response interceptor called', response);
  111.     // 可以在这里修改响应数据
  112.     return response;
  113.   },
  114.   error => {
  115.     // 对响应错误做点什么
  116.     return Promise.reject(error);
  117.   }
  118. );
  119. // 发送请求
  120. dispatchRequest({ url: 'https://api.example.com/data' })
  121.   .then(response => {
  122.     console.log('Response received:', response);
  123.   })
  124.   .catch(error => {
  125.     console.error('Error occurred:', error);
  126.   });
复制代码
以上代码是一个高度简化的版本,用于展示 Axios 拦截器是怎样实现的。如果你对 Axios 的拦截器实现细节感兴趣,建议查看 Axios 的官方 GitHub 仓库中的源码。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

熊熊出没

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表