手写axios源码系列四:interceptor拦截器

news2024/9/16 15:39:41

在这里插入图片描述

文章目录

  • 一、拦截器 interceptor
    • 1、创建 InterceptorManager.js 文件
    • 2、Axios 中实例化 InterceptorManager 类
    • 3、总结

在本系列的第一篇章节 手写axios源码系列一:axios核心知识点 中已经介绍过一些拦截器的基础知识,可知拦截器分为:

  • 请求拦截器:axios.interceptors.request
  • 响应拦截器:axios.interceptors.response

使用 use 方法添加拦截器,并且可以添加多个拦截器。use 方法接收两个函数为参数:

  1. fulfilled:传递给 promise.then() 的第一个成功的回调
  2. rejected:传递给 promise.then() 的第二个失败的回调

use 使用方式如下:

  • axios.interceptors.request.use(fulfilled, rejected)
  • axios.interceptors.response.use(fulfilled, rejected)

一、拦截器 interceptor

1、创建 InterceptorManager.js 文件

export default class InterceptorManager {
	constructor(){
		// 因为拦截器可以添加多个,所以用数组保存
		this.handlers = [];
	},
	// 原型对象的 use 方法
	use(fulfilled, rejected){
		this.handlers.push({ fulfilled, rejected })
	}
}

2、Axios 中实例化 InterceptorManager 类

在发送请求前,需要处理请求拦截器,而响应之后需要处理响应拦截器,最后再返回处理过后的响应数据;所以拦截器的处理逻辑放在 Axios.prototype.request 方法中。

import InterceptorManager from "./InterceptorManager.js";

export default class Axios {
	constructor(config){
		this.defaults = config;
		this.interceptors = {
			request: new InterceptorManager(),  // 实例化请求拦截器
			response: new InterceptorManager()  // 实例化响应拦截器
		}
	}
	request(configOrUrl, config){
		if(typeof configOrUrl === "string"){
			config.url = configOrUrl
		} else {
			config = {
				...configOrUrl,
				...config
			}
		}
		// 将 config包装为一个成功状态的 promise对象
		let promise = Promise.resolve(config);
		// 创建执行链,这里调用 dispatchRequest方法以发送请求,undefined起到一个占位符的作用
		const chain = [dispatchRequest, undefined];
		/** 拦截器的处理逻辑 */
		// 将请求拦截器添加到 chain的头部
		this.interceptors.request.handlers.forEach(interceptor => {
			chain.unshift(interceptor.fulfilled, interceptor.rejected)
		});
		// 将响应请求器添加到 chain的尾部
		this.interceptors.response.handlers.forEach(interceptor => {
			chain.push(interceptor.fulfilled, interceptor.rejected)
		});
		// 执行所有的拦截器(一个成功,一个失败)
		while(chain.length){
			promise = promise.then(chain.shift(), chain.shift());
		}
		// 发送请求后返回的是一个 promise对象
		return promise;
}

如果有2个请求拦截器,2个响应拦截器,则拦截器整体添加流程如下图:

在这里插入图片描述
执行链 chain 执行时是从数组索引0开始执行的,所以先执行 请求拦截器2,再执行请求拦截器1,然后执行 dispatchRequest发送请求,请求响应后执行 响应拦截器1响应拦截器2,最后返回 response

3、总结

拦截器这里的逻辑其实就是将拦截器添加到数组的方式不同,所以产生的结果也不同,明白 unshift 与 push 将数据添加到数组的方式,也就明白拦截器的执行方式了。后面执行链执行时,使用 shift 从 chain 中取数据,会改变 chain 的长度,明白这些点也就难不住你了。so easy。

还有一点,就是声明执行链 chain 时,有一个 undefined 占位符。原因就是 promise.then(chain.shift(), chain.shift()) 代码执行时,每次从 chain 中取出成对的回调函数,一个成功,一个失败,放到相应的位置执行。如果没有 undefined 占位,当取到 dispatchRequest 回调函数时,下一个取的就是 响应成功1 的回调函数放到 then 中失败回调的位置,导致响应出错。这里为了保证程序的正确运行,所以使用了 undefined 占位。

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

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

相关文章

24从零开始学Java之如何正确地使用一维数组

作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 在之前的文章中,壹哥给大家讲解了java里的顺序结构、分支结构、循环结构等内容&#xff0…

diffusion扩散模型之hello world

以mnist图像生成样本为例,详细解释diffusion的每个步骤和过程 扩散模型包括两个过程:前向过程(forward process)和反向过程(reverse process),其中前向过程又称为扩散过程(diffusio…

Taro React组件开发(9) —— RuiCountDown 倒计时

1. 需求实现 根据传入的格式,返回倒计时的文本字段;时间格式需要自定义,需要返回对应时间的值;对毫秒级的时间进行渲染;自定义时间的样式;手动控制倒计时的开始、暂停和重置。2. 需求实现 查找网上类似组件 uView CountDown 倒计时;由于 uView CountDown 倒计时 是使用 …

深度学习 - 42.特征交叉与 SetNET、Bilinear Interaction 与 FiBiNet

目录 一.引言 二.摘要 - ABSTRACT 三.介绍 - INTRODUCTION 四.相关工作 - RELATED WORK 1.因式分解机及其变体 - Factorization Machine and Its relevant variants 2. 基于深度学习的点击率模型 - Deep Learning based CTR Models 3.SENET Module 五.FiBiNet Model 1…

【嵌入式】HC32F定时器PWM捕获+APC芯片实现模拟AD采样

目录 一 项目背景 二 原理说明 三 设计实现——定时器初始化 四 设计实现——PWM捕获 五 梳理总结 一 项目背景 目前使用了TI的ADC采样芯片ADS1018实现模拟量4-20mA/0-20mA的采样,原理是将外部输入的模拟量信号4-20mA,经由并联的两个100Ω电阻&#…

day-01 one-day projects

个人名片: 😊作者简介:一名大一在校生,web前端开发专业 🤡 个人主页:python学不会123 🐼座右铭:懒惰受到的惩罚不仅仅是自己的失败,还有别人的成功。 🎅**学习…

AIGC席卷,抖快、阅文、知乎大战网文圈

配图来自Canva可画 成熟的网文市场,时不时进来一条鲶鱼。 经历了二十几个夏秋秋冬,网文市场形成了阅文、晋江、七猫、番茄等平台割据一方稳定的市场格局。后来暗自布局网文市场的知乎、抖音、快手等新玩家开始浮出水面,未来的市场纷争下或许…

Docker持久化方式-v和-volume的区别

docker数据的持久化一直用的是-v的方式,又叫Bind Mounts(目录绑定),偶然间发现还有一种通过卷轴来实现持久化的方式,翻了下资料,整理了一下两种方式使用的场景。 -v(Bind Mounts) …

使用 Apache PDFBox 操作PDF文件

简介 Apache PDFBox库是一个用于处理PDF文档的开源Java工具。该项目允许创建新的PDF文档,操作现有PDF文档,并从PDF文档中提取内容。Apache PDFBox还包括几个命令行实用程序。 Apache PDFBox的主要功能如下: 从PDF文件中提取Unicode文本。将…

浅析提高倾斜摄影超大场景的三维模型轻量化的数据质量关键技术

浅析提高倾斜摄影超大场景的三维模型轻量化的数据质量关键技术 倾斜摄影超大场景的三维模型轻量化的质量关键技术主要包括: 1、保持数据精度。在进行轻量化处理时,必须确保数据的精度不受损失,否则会影响后续分析和应用方案。因此&#xff0…

接口测试不再难。这篇文章让你在5分钟内掌握接口自动化测试用例

目录 摘要: 一、背景 二、测试用例设计 三、测试脚本实现 四、最佳实践和技巧 总结 摘要: 本文介绍了接口自动化测试的重要性,并提供了一个简单的测试用例,涵盖了设计、条件、步骤和数据方面的考虑。通过使用Python中的req…

C/C++|物联网开发入门+项目实战|函数输入与输出|值传递|地址传递|连续空间的传递|嵌入式C语言高级|C语言函数的使用(1)-学习笔记(11)

文章目录 函数概述输入参数示例:值传递地址传递连续空间的传递 参考: 麦子学院-嵌入式C语言高级-C语言函数的使用 函数概述 一堆代码的集合,用一个标签去描述它 复用化,降低冗余度 标签 ------ 函数名 函数和数组都属于内存空间&#xff0c…

C语言system讲解

‘system’是C语言标准库中的一个函数,它的作用是对计算机系统进行操作,如创建文件夹,打开文件夹,清空屏幕等等,下面介绍一下常用的几个system命令 system函数原型 int system(const char* command); command是字符…

联发科的好日子结束,出货量暴跌,高通稳住阵脚并开始反击

在手机芯片市场连续3年时间顺风顺水之后,联发科终于迎来了高通的反击,特别是骁龙8G2的发布更是导致联发科在手机芯片市场的步步后退,推动了高通的反弹。 一、形势有利于高通 高通此前的骁龙8G1和骁龙888因出现发热问题,因此被誉为…

4. 线性表

4. 线性表 线性表是最基本、最简单、也是最常用的一种数据结构(逻辑结构)。一个线性表是n个具有相同特性的数据元素的有限序列。 前驱元素: 若A元素在B元素的前面,则称A为B的前驱元素 后继元素: 若B元素在A元素的后面,则称B为…

【翻译一下官方文档】之uniapp的界面弹框交互

大致分 3 种 普通提示loading框弹出选项 我个人理解就是大致知道有些什么,有啥功能,用到的时候,直接去用,不会的回来翻看文档 uni.showToast(OBJECT) 参数类型必填说明平台差异说明titleString是提示的内容,长度与…

C++ 多态详解

目录 多态的概念 定义 C直接支持多态条件 举例 回顾继承中遇到的问题 虚函数-虚函数指针-虚函数列表 虚函数 虚函数指针 虚函数列表 虚函数调用流程 虚函数于普通成员函数的区别 多态的概念 定义 多态:相同的行为方式导致了不同的行为结果,同一行…

【翻译一下官方文档】之uniapp的.sync修饰符

先用一个案例引出.sync修饰符 就是这样一个场景 父组件直接修改状态A当然没问题,但是子组件不能直接修改状态A,因为单向数据流限制 单向数据流 uni-app官网 所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会…

AFP vs SMB vs NFS: 谁是最好的数据传输协议?

目录 SMB: 什么是SMB 协议? NFS: 什么是NFS协议? AFP: 设么是AFP协议? 如何选择合适的传输协议? 场景1: 大型企业 场景2: 小型网站设计公司 场景3: Linux软件开发组 可以在互联网上使用这些协议吗? AFP vs SMB vs NFS …

Docker的安装和镜像容器的基本操作

Docker的安装和镜像容器的基本操作 Docker 概述Docker与虚拟机的区别namespace的六项隔离Docker核心概念 安装 DockerDocker 镜像操作搜索镜像获取镜像镜像加速下载查看镜像信息查看下载的镜像文件信息查看下载到本地的所有镜像根据镜像的唯一标识 ID 号,获取镜像详…