当前位置: 首页 > news >正文

【axios】的浅度分析

一、Axios的拦截器能干些什么?

Axios拦截器的实现原理主要涉及两个方面:请求拦截器和响应拦截器,它们分别在请求发送前和响应返回后进行预处理和后处理。

Axios内部维护了两个数组,一个用于存储请求拦截器,另一个用于存储响应拦截器。每个拦截器都是一个函数,这些函数按照它们在数组中定义的顺序被依次执行。

1、请求拦截器:

当Axios发起一个请求时,会首先遍历并执行请求拦截器数组中的每个函数。
请求拦截器的作用是在请求发送前对请求进行修改或添加一些公共的逻辑,例如给每个请求体都加上token,或者修改请求的配置,如headers、url、params等。此外,也可以在此阶段取消请求。
请求拦截器的修改或添加的配置将被用于之后的请求发送。

2、响应拦截器:

一旦请求被发送并得到响应,Axios会遍历并执行响应拦截器数组中的每个函数。
响应拦截器的作用是在响应返回后对响应进行特定的处理,例如对返回的数据进行统一处理或对特定的错误进行处理。
如果响应是一个正常的响应,可以直接返回数据或对数据进行修改。如果响应是一个错误(例如,404或500状态码),可以进行错误处理或重试逻辑。

使用Axios拦截器的好处包括统一处理公共逻辑,减少重复代码,提高代码的可读性和可维护性。同时,也可以在请求或响应不符合预期时进行统一处理,提高程序的健壮性。

需要注意的是,在使用Axios拦截器时,应确保请求拦截器在响应拦截器之前执行,避免逻辑上的错误。此外,应避免在拦截器中修改原始请求或响应数据,以免影响其他拦截器或请求处理器的处理结果。同时,应考虑性能问题,避免在拦截器中进行耗时的操作。

综上所述,Axios拦截器的实现原理主要基于其内部维护的请求和响应拦截器数组,通过依次执行这些拦截器函数,实现对请求和响应的预处理和后处理。

二、Axios 源码中,拦截器是怎么实现的?(最简化的理解)

Axios 的拦截器实现基于 Axios 的核心原理,即 Axios 实例是一个包含请求和响应拦截器堆栈的对象。当发出请求或接收响应时,Axios 会遍历这些拦截器,并按照添加的顺序执行请求拦截器,以及按照相反的顺序执行响应拦截器。
在 Axios 的源码中,拦截器是通过一个 AxiosInterceptorManager 实例来管理的,它维护了一个拦截器数组。每个拦截器都是一个包含 fulfilledrejected 函数的对象。这两个函数分别对应于拦截器成功处理和拦截器处理出错的情况。
以下是 Axios 拦截器管理器的一个简化版本,展示了其核心实现思路:

class InterceptorManager {constructor() {this.handlers = []; // 存储拦截器的数组}use(fulfilled, rejected) {this.handlers.push({fulfilled: fulfilled,rejected: rejected});return this.handlers.length - 1; // 返回拦截器的ID}eject(id) {if (this.handlers[id]) {this.handlers[id] = null; // 移除拦截器}}forEach(fn) {this.handlers.forEach((h) => {if (h !== null) {fn(h);}});}
}

在发送请求或接收响应时,Axios 会创建一个 promise 链,并通过 forEach 方法将拦截器中的 fulfilledrejected 函数添加到这个链中。这样,每个拦截器都可以对请求或响应进行处理,然后将结果传递到链的下一个拦截器,或者在出错时结束链的执行。
PS:注意,上面说的是拦截管理器,并非下面要说的拦截器

axios.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {chain.unshift(interceptor.fulfilled, interceptor.rejected);
});axios.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {chain.push(interceptor.fulfilled, interceptor.rejected);
});

在 Axios 的完整实现中,这个拦截器机制被集成到了 Axios 的请求发送和响应处理流程中。通过这种方式,Axios 可以在发送请求之前和接收响应之后,但在用户定义的 .then.catch 执行之前,插入自定义的逻辑。
请注意,这里提供的代码只是为了说明 Axios 拦截器的实现原理,并不是 Axios 源码的完整复制。

三、高度简化的源码(axios拦截器实现源码)

Axios 拦截器的实现源码涉及到其核心模块的设计。Axios 允许你注册请求拦截器和响应拦截器,这些拦截器在请求发送前和响应返回后进行相应的处理。以下是简化的 Axios 拦截器实现源码的概述:

// 假设 Axios 实例有一个 interceptors 对象,其中包含了 request 和 response 两个数组
const instance = {interceptors: {request: [],response: []}
};// 请求拦截器的函数定义
function onFulfilled(fulfilled, rejected) {return function (config) {return new Promise((resolve, reject) => {try {const result = fulfilled(config);if (result && typeof result.then === 'function') {result.then(resolvedConfig => {resolve(resolvedConfig);}, rejected);} else {resolve(result);}} catch (error) {reject(error);}};};
}// 响应拦截器的函数定义
function onFulfilledResponse(fulfilled, rejected) {return function (response) {return new Promise((resolve, reject) => {try {const result = fulfilled(response);if (result && typeof result.then === 'function') {result.then(resolvedResponse => {resolve(resolvedResponse);}, rejected);} else {resolve(result);}} catch (error) {reject(error);}};};
}// 添加请求拦截器
instance.interceptors.request.use = function (fulfilled, rejected) {this.interceptors.request.push({fulfilled: onFulfilled(fulfilled, rejected),rejected: rejected});return this;
};// 添加响应拦截器
instance.interceptors.response.use = function (fulfilled, rejected) {this.interceptors.response.push({fulfilled: onFulfilledResponse(fulfilled, rejected),rejected: rejected});return this;
};// 简化版的请求发送函数,用于展示拦截器如何处理
function dispatchRequest(config) {return new Promise((resolve, reject) => {// 遍历并执行请求拦截器const chain = [Promise.resolve(config)];instance.interceptors.request.forEach(interceptor => {chain.unshift(interceptor.fulfilled, interceptor.rejected);});// 遍历并执行响应拦截器chain.push(dispatchRequestToServer); // 假设这个函数是实际发送请求到服务器的函数while (chain.length) {const currentInterceptor = chain.shift();const nextInterceptor = chain.shift();if (typeof currentInterceptor === 'function') {currentInterceptor(config).then(chain => {if (typeof nextInterceptor === 'function') {nextInterceptor(chain);} else {resolve(chain);}}).catch(reject);}}});
}// 假设函数,用于实际发送请求到服务器
function dispatchRequestToServer(config) {// 这里应该是实际的请求发送逻辑,为了简化,我们直接返回一个模拟的响应return Promise.resolve({data: 'Response data'});
}// 使用拦截器
instance.interceptors.request.use(config => {// 在发送请求之前做些什么console.log('Request interceptor called', config);// 可以在这里修改config对象return config;},error => {// 对请求错误做些什么return Promise.reject(error);}
);instance.interceptors.response.use(response => {// 对响应数据做点什么console.log('Response interceptor called', response);// 可以在这里修改响应数据return response;},error => {// 对响应错误做点什么return Promise.reject(error);}
);// 发送请求
dispatchRequest({ url: 'https://api.example.com/data' }).then(response => {console.log('Response received:', response);}).catch(error => {console.error('Error occurred:', error);});

以上代码是一个高度简化的版本,用于展示 Axios 拦截器是如何实现的。如果你对 Axios 的拦截器实现细节感兴趣,建议查看 Axios 的官方 GitHub 仓库中的源码。

相关文章:

  • 【CSS】计算属性 calc 函数
  • leetcode-设计LRU缓存结构-112
  • Matlab|基于PMU相量测量单元进行电力系统电压幅值和相角状态估计
  • 2024最新 Jenkins + Docker实战教程(七)- Jenkins实现远程传输和自动部署
  • MS Excel: 高亮当前行列 - 保持原有格式不被改变
  • 代码随想录-算法训练营day47【动态规划09:打家劫舍、打家劫舍II、打家劫舍III】
  • 基于python实现生命游戏
  • 【C++】---二叉搜索树
  • 小型海外仓如何选择第三方海外仓系统:多看多对比,性价比优先
  • 数据集的读取和处理
  • 【微机原理及接口技术】可编程计数器/定时器8253
  • C++标准模板(STL)- C 内存管理库 - 分配并清零内存 (std::calloc)
  • 怎么从视频中提取音频?这里有三种提取妙招
  • 19 - grace数据处理 - 补充 - 地下水储量计算过程分解 - 冰后回弹(GIA)改正
  • 代码随想录算法训练营第22天(py)| 二叉树 | 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • Git的一些常用操作
  • JavaScript DOM 10 - 滚动
  • JWT究竟是什么呢?
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • quasar-framework cnodejs社区
  • Redis 懒删除(lazy free)简史
  • 测试开发系类之接口自动化测试
  • 从0到1:PostCSS 插件开发最佳实践
  • 每天一个设计模式之命令模式
  • 前端临床手札——文件上传
  • 如何设计一个比特币钱包服务
  • 如何设计一个微型分布式架构?
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 通过npm或yarn自动生成vue组件
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • ​VRRP 虚拟路由冗余协议(华为)
  • !!Dom4j 学习笔记
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (3)(3.5) 遥测无线电区域条例
  • (vue)页面文件上传获取:action地址
  • (二)PySpark3:SparkSQL编程
  • (二开)Flink 修改源码拓展 SQL 语法
  • (分类)KNN算法- 参数调优
  • (含笔试题)深度解析数据在内存中的存储
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (排序详解之 堆排序)
  • (七)Knockout 创建自定义绑定
  • (十)c52学习之旅-定时器实验
  • (十一)手动添加用户和文件的特殊权限
  • (算法)前K大的和
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (微服务实战)预付卡平台支付交易系统卡充值业务流程设计
  • (五)MySQL的备份及恢复
  • (转)详解PHP处理密码的几种方式