深入理解 Axios 拦截器的执行链机制

深入理解 Axios 拦截器的执行链机制

在现代前端开发中,Axios 是最流行的 HTTP 请求库之一,而 拦截器(Interceptor)功能是其核心特性之一。通过拦截器,我们可以在请求发送前或响应返回后进行灵活的预处理或后处理。然而,很多人并不了解拦截器在 Axios 内部是如何构建和执行的。本文将深入剖析 Axios 拦截器的 执行链机制,帮助更多开发者掌握这一重要知识。


1. Axios 拦截器的结构

拦截器分为两类:

  • 请求拦截器(Request Interceptors):在请求被发送前执行,可以用来修改请求配置(如添加认证 Token)。
  • 响应拦截器(Response Interceptors):在请求返回后执行,可以用来处理响应数据或错误(如统一错误处理)。

拦截器存储结构

Axios 使用一个 InterceptorManager 类来管理拦截器。每个拦截器由两个回调函数组成:fulfilled(成功时执行)和 rejected(失败时执行)。这些拦截器被保存在 handlers 数组中。

class InterceptorManager {constructor() {this.handlers = []; // 存储拦截器的数组}use(fulfilled, rejected) {this.handlers.push({ fulfilled, rejected });return this.handlers.length - 1; // 返回拦截器索引,用于删除}eject(id) {if (this.handlers[id]) {this.handlers[id] = null; // 通过索引禁用拦截器}}
}

2. Axios 拦截器的执行链

Axios 的执行链是一个由 Promise 串联的动态数组,其结构如下:

拦截器执行链的三部分

  1. 左侧:请求拦截器(Request Interceptors)

    • 顺序:按照注册顺序的 逆序 执行(后注册的先执行)。
    • 作用:在请求被发送之前对配置对象进行处理。
  2. 中间:核心逻辑(dispatchRequest)

    • 负责实际的 HTTP 请求。
    • 分隔了请求拦截器和响应拦截器。
  3. 右侧:响应拦截器(Response Interceptors)

    • 顺序:按照注册顺序的 正序 执行(先注册的先执行)。
    • 作用:在请求返回后对响应数据进行处理。

执行链的构建代码

以下是 Axios 拦截器执行链的源码片段:

Axios.prototype.request = function request(config) {const chain = [dispatchRequest, undefined]; // 中间逻辑初始化let promise = Promise.resolve(config); // 初始化 Promise 链// 添加请求拦截器(从前插入,后注册的先执行)this.interceptors.request.forEach((interceptor) => {chain.unshift(interceptor.fulfilled, interceptor.rejected || undefined);});// 添加响应拦截器(从后追加,先注册的先执行)this.interceptors.response.forEach((interceptor) => {chain.push(interceptor.fulfilled, interceptor.rejected || undefined);});// 执行拦截器链while (chain.length) {promise = promise.then(chain.shift(), chain.shift());}return promise;
};

3. 请求拦截器与响应拦截器的执行顺序

通过上面的代码可以看出,Axios 是如何动态构建拦截器链的。下面以一个例子说明拦截器的执行顺序:

示例代码

// 注册两个请求拦截器
axios.interceptors.request.use((config) => {console.log('请求拦截器 1');return config;
});axios.interceptors.request.use((config) => {console.log('请求拦截器 2');return config;
});// 注册两个响应拦截器
axios.interceptors.response.use((response) => {console.log('响应拦截器 1');return response;
});axios.interceptors.response.use((response) => {console.log('响应拦截器 2');return response;
});// 发起请求
axios.get('/example');

执行链的构建结果

[请求拦截器 2, 请求拦截器 1, dispatchRequest, undefined, 响应拦截器 1, 响应拦截器 2]

执行顺序

  1. 请求拦截器(从左到中间):
    • 请求拦截器 2
    • 请求拦截器 1
  2. 核心逻辑(中间部分):
    • dispatchRequest 执行实际的 HTTP 请求。
  3. 响应拦截器(从中间到右):
    • 响应拦截器 1
    • 响应拦截器 2

最终输出:

请求拦截器 2
请求拦截器 1
响应拦截器 1
响应拦截器 2

4. 拦截器中的 unshiftpush

在 Axios 的源码中,拦截器的添加方式直接影响了执行顺序:

  1. 请求拦截器
    使用 unshift 添加到数组头部,确保后注册的拦截器优先执行。

    chain.unshift(interceptor.fulfilled, interceptor.rejected);
    
  2. 响应拦截器
    使用 push 添加到数组尾部,确保先注册的拦截器优先执行。

    chain.push(interceptor.fulfilled, interceptor.rejected);
    

5. 为什么要分隔拦截器?

在 Axios 中,dispatchRequest 既是 HTTP 请求的核心逻辑,也是请求和响应拦截器的天然分隔点。分隔的意义如下:

  1. 分工明确

    • 请求拦截器仅处理请求数据(如添加认证信息、修改 URL)。
    • 响应拦截器仅处理返回数据(如解析 JSON、统一错误处理)。
  2. Promise 链式调用的完整性

    • Axios 通过 undefined 占位确保 Promise 链不会断裂,即使某个拦截器没有 rejected 方法。

6. 总结

Axios 的拦截器机制为开发者提供了强大的灵活性和扩展性,其核心逻辑包括:

  • 请求拦截器通过 unshift 插入链头,保证后注册的拦截器优先执行。
  • 响应拦截器通过 push 插入链尾,保证先注册的拦截器优先执行。
  • 中间逻辑 dispatchRequest 是请求和响应的分界点。
  • 使用动态链式调用确保拦截器的执行顺序和逻辑一致性。

掌握拦截器的内部实现,有助于我们更高效地调试和优化代码。希望本文能够帮助更多开发者深入理解 Axios 的核心原理,进而提升开发效率!


如果您觉得这篇文章对您有所帮助,欢迎点赞、转发,或留下评论一起讨论!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/61828.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ElementUI:el-drawer实现在父组件区域内打开抽屉组件非全屏

我们在开发ElementUI的时候遇到抽屉组件全屏的问题,但是我们需要在指定div中展示出来,上代码: 1、在el-drawer中增加属性 el-drawerstyle"position: absolute"z-index"-1":append-to-body"false">// do s…

电机驱动MCU介绍

电机驱动MCU是一种专为电机控制设计的微控制器单元,它集成了先进的控制算法和高性能的功率输出能力。 电机驱动MCU采用高性能的处理器核心,具有快速的运算速度和丰富的外设接口。它内置了专业的电机控制算法,包括PID控制、FOC(Fi…

Ubuntu Linux操作系统

一、 安装和搭建 Thank you for downloading Ubuntu Desktop | Ubuntu (这里我们只提供一个下载地址,详细的下载安装可以参考其他博客) 二、ubuntu的用户使用 2.1 常规用户登陆方式 在系统root用户是无法直接登录的,因为root用户的权限过…

Vue 前端 el-input 如何实现输入框内容始终添加在尾部%

要在 el-input 输入框的尾部添加 %,你可以通过两种方式来实现: 使用 suffix 插槽:这是最直接和最常用的方法。使用 append 插槽:如果你需要在输入框内或者右侧显示其他内容。 方法 1:使用 suffix 插槽 el-input 提供…

开箱即用,阿里开源!专业AI 聊天界面工具包:Ant Design X

Ant Design X是一个基于Ant Design体系的创新解决方案,为构建高效的AI交互界面提供了便利和支持。从精细的原子组件到快速集成的模型服务,Ant Design X让开发者能轻松应对各种需求。本文将结合实际场景,展示Ant Design X的功能与使用方法。 为…

kernel crash数据解析

crash数据解析 crash解析工具下载和编译方法如下: git clone https://github.com/crash-utility/crash.git cd crash; make targetARM64 crash工具解析ramdump文件: 1. 将dump 出来的ramdump 文件拷贝到 Linux 系统 2. 找到当前Linux 内核对应的vm…

git查看本地库对应的远端库的地址

git查看本地库对应的远端库的地址 git remote -v 如果想要查看特定的远端库的url地址,可以使用如下命令,其中origin是默认的远端库的名称,可以使用其他远端库的名称 get remote get-url origin

C# yield 关键字

文章目录 前言一、yield 关键字的语法形式及使用场景(一)yield return(二)yield break 二、yield 关键字的工作原理三、yield 关键字的优势与应用场景(一)优势(二)应用场景 前言 在 …

QT6学习第八天 QFrame 类

QT6学习第八天 QFrame 类族QLabel 标签部件按钮部件QLineEdit 行编辑器部件QAbstractSpinBoxQAbstractSlider 今天来学一学 QFrame 类。 QFrame 类族 QFrame 类是带有边框的部件的基类。它的子类包括常用的标签部件 QLabel、以及 QLCDNumber、QSplitter、QStackedWidget、QToo…

[node.js] [HTTP/S] 实现 requests 发起 HTTP/S/1.1/2.0 请求

node.js 使用 V8 引擎来编译运行 javascript 代码,与浏览器中的环境不同的是,node.js 不包含 DOM 和 BOM 模块。 本文使用 node.js 的官方库来实现一个简单的 requests() 函数,可以用来发送 HTTP/1.1 和 HTTP/2.0 的请求。有关 HTTP/1.1 和 …

spring boot 微服务 redis集群配置

spring boot 微服务 redis集群配置 1.redis 有三种集群模式 主从模式 哨兵模式&#xff08;Sentinel&#xff09; Cluster模式引入redis依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis&…

【2024 re:Invent现场session参加报告】打造生成式AI驱动的车间智能助手

前言 这次参加了 re:Invent 2024 的 Builders Session 「Building a generative AI–powered shop floor assistant」&#xff0c;在这里和大家分享一下内容&#xff01; Session 概要 Learn how to build a generative AI assistant to analyze data from industrial IoT se…

Golang HTTP 标准库的使用实现原理

一.使用&#xff1a; 启动http服务&#xff1a; package mainimport "net/http"func main() {http.HandleFunc("/wecunge", func(w http.ResponseWriter, r *http.Request) {w.Write([]byte("wecunge"))})http.ListenAndServe(":8080&quo…

深入理解 GitHub 高级应用:从分支管理到自动化工作流

GitHub 是世界上最流行的代码托管平台&#xff0c;提供了丰富的功能来帮助开发者管理和协作项目。从基本的代码版本控制到复杂的协作工作流&#xff0c;GitHub 提供了大量高级功能来提升团队效率和代码质量。本文将介绍 GitHub 的一些高级应用和功能&#xff0c;包括分支管理、…

【C++】数组

1.概述 所谓数组&#xff0c;就是一个集合&#xff0c;该集合里面存放了相同类型的数据元素。 数组特点&#xff1a; &#xff08;1&#xff09;数组中的每个数据元素都是相同的数据类型。 &#xff08;2&#xff09;数组是有连续的内存空间组成的。 2、一维数组 2.1维数组定…

速盾:高防cdn的搜索引擎回源是什么?

高防CDN&#xff08;Content Delivery Network&#xff09;是一种用于加速网站访问速度和增加安全性的服务&#xff0c;它通过将静态和动态内容缓存在全球分布的服务器上&#xff0c;从而将用户请求的响应时间降至最低&#xff0c;并提供有效的防御攻击的能力。在实际使用过程中…

[VUE]框架网页开发02-如何打包Vue.js框架网页并在服务器中通过Tomcat启动

在现代Web开发中&#xff0c;Vue.js已经成为前端开发的热门选择之一。然而&#xff0c;将Vue.js项目打包并部署到生产环境可能会让一些开发者感到困惑。本文将详细介绍如何将Vue.js项目打包&#xff0c;并通过Tomcat服务器启动运行。 1. 准备工作 确保你的项目能够正常运行,项…

ESP32-S3模组上跑通ES8388(13)

接前一篇文章&#xff1a;ESP32-S3模组上跑通ES8388&#xff08;12&#xff09; 二、利用ESP-ADF操作ES8388 2. 详细解析 上一回解析了es8388_init函数中的第6段代码&#xff0c;本回继续往下解析。为了便于理解和回顾&#xff0c;再次贴出es8388_init函数源码&#xff0c;在…

openEuler 22.03 使用cephadm安装部署ceph集群

目录 目的步骤规格步骤ceph部署前准备工作安装部署ceph集群ceph集群添加node与osdceph集群一些操作组件服务操作集群进程操作 目的 使用ceph官网的cephadm无法正常安装&#xff0c;会报错ERROR: Distro openeuler version 22.03 not supported 在openEuler上实现以cephadm安装部…

DevOps工程技术价值流:GitLab源码管理与提交流水线实践

在当今快速迭代的软件开发环境中&#xff0c;DevOps&#xff08;开发运维一体化&#xff09;已经成为提升软件交付效率和质量的关键。而GitLab&#xff0c;作为一个全面的开源DevOps平台&#xff0c;不仅提供了强大的版本控制功能&#xff0c;还集成了持续集成/持续交付(CI/CD)…