一文解析axios源码

写了几年项目,也用了几年的axios,但是一直也不是很了解其中的原理,为啥他能请求前拦截,也为啥他能响应后拦截,正好有空,所以对他的源码进行分析,从github把他的源码拉下来进行分析:
在这里插入图片描述
从package.json可以看出主入口:index.js
在这里插入图片描述
查看/lib/axios.js
在这里插入图片描述

lib/axios.js 主要一个createInstance 创建一个实例的方法,我们使用axios的时候,都是这样使用的,如下面的代码所示,axios.create就是上面的方法创建的

// 创建axios实例
const service = axios.create({baseURL: '',timeout: 20000, // 请求超时时间headers: {'Content-Type': 'multipart/form-data'}
})

在继续看看new Axios里面干了啥,找到lib/core/Axios.js文件,分解来看,剔除了一些非核心代码,核心代码如下:

class Axios {constructor(instanceConfig) {this.defaults = instanceConfig;this.interceptors = {request: new InterceptorManager(),response: new InterceptorManager()};async request(configOrUrl, config) {try {return await this._request(configOrUrl, config);} catch (err) }}_request(configOrUrl, config) {const requestInterceptorChain = [];let synchronousRequestInterceptors = true;this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);});const responseInterceptorChain = [];this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);});let promise;let i = 0;let len;if (!synchronousRequestInterceptors) {const chain = [dispatchRequest.bind(this), undefined];chain.unshift.apply(chain, requestInterceptorChain);chain.push.apply(chain, responseInterceptorChain);len = chain.length;promise = Promise.resolve(config);while (i < len) {promise = promise.then(chain[i++], chain[i++]);}return promise;}len = requestInterceptorChain.length;let newConfig = config;i = 0;while (i < len) {const onFulfilled = requestInterceptorChain[i++];const onRejected = requestInterceptorChain[i++];try {newConfig = onFulfilled(newConfig);} catch (error) {onRejected.call(this, error);break;}}try {promise = dispatchRequest.call(this, newConfig);} catch (error) {return Promise.reject(error);}i = 0;len = responseInterceptorChain.length;while (i < len) {promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]);}return promise;}
}
// Provide aliases for supported request methods
utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {/*eslint func-names:0*/Axios.prototype[method] = function(url, config) {return this.request(mergeConfig(config || {}, {method,url,data: (config || {}).data}));};
});
utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {/*eslint func-names:0*/function generateHTTPMethod(isForm) {return function httpMethod(url, data, config) {return this.request(mergeConfig(config || {}, {method,headers: isForm ? {'Content-Type': 'multipart/form-data'} : {},url,data}));};}Axios.prototype[method] = generateHTTPMethod();Axios.prototype[method + 'Form'] = generateHTTPMethod(true);
});

核心步骤解析:
1、创建Axios类,构造函数中定义请求拦截和响应拦截

查看lib/core/InterceptorManager.js 文件new InterceptorManager(),主要是一个handlers数组,即

class Axios {constructor(instanceConfig) {this.defaults = instanceConfig;this.interceptors = {request: [],response:[]};} 
}

2、查看上述核心代码最后两段utils.forEach([‘delete’, ‘get’, ‘head’, ‘options’],即把这些都放到Axios.prototype[method]的原型上,当我们在使用axios.get的时候就是调用这里,而这里的方法其实就是调用this.request,而调用this.request则是调用_request方法
在这里插入图片描述

3、_request方法分析

_request(configOrUrl, config) {config = mergeConfig(this.defaults, config); // 默认config与传jinlaid的config进行合并// Set config.methodconfig.method = (config.method || this.defaults.method || 'get').toLowerCase();// config的method优先从传进来的取,如果使用者没有传递,则使用默认config里面的method,默认的没有则默认getconst requestInterceptorChain = [];let synchronousRequestInterceptors = true;this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);});const responseInterceptorChain = [];this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);});let promise;let i = 0;let len;if (!synchronousRequestInterceptors) {const chain = [dispatchRequest.bind(this), undefined];chain.unshift.apply(chain, requestInterceptorChain);chain.push.apply(chain, responseInterceptorChain);len = chain.length;promise = Promise.resolve(config);while (i < len) {promise = promise.then(chain[i++], chain[i++]);}return promise;}len = requestInterceptorChain.length;let newConfig = config;i = 0;while (i < len) {const onFulfilled = requestInterceptorChain[i++];const onRejected = requestInterceptorChain[i++];try {newConfig = onFulfilled(newConfig);} catch (error) {onRejected.call(this, error);break;}}try {promise = dispatchRequest.call(this, newConfig);} catch (error) {return Promise.reject(error);}i = 0;len = responseInterceptorChain.length;while (i < len) {promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]);}return promise;}

你可能有点懵,我们先来看看axios的请求拦截器和响应拦截器是怎么使用的,我们是不是都跟下面的代码一样使用的拦截器?

// 请求拦截器
service.interceptors.request.use(config => },error => {}
)// 响应拦截器
service.interceptors.response.use(response => },error => {}
)

查看InterceptorManager.js代码,这里的use方法就是往handlers里面push
在这里插入图片描述
再看_request核心代码:先把this.interceptors.request请求拦截器数组里面全都用unshift放入到requestInterceptorChain数组里面,把this.interceptors.response响应拦截器数组里面的全部用push放入到responseInterceptorChain,然
const chain = [dispatchRequest.bind(this), undefined];
chain.unshift.apply(chain, requestInterceptorChain);
chain.push.apply(chain, responseInterceptorChain);

请求拦截器+当前请求+响应拦截器的这是不是连接起来了? 这就是为什么在你发一个请求的时候,因为他是一条链,先zhi行请求拦截器,等所有的拦截器执行完,在执行当前请求,等你当前请求执行完再执行响应拦截器,全连起来了!

// filter out skipped interceptorsconst requestInterceptorChain = [];let synchronousRequestInterceptors = true;this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {return;}synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);});const responseInterceptorChain = [];this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);});const chain = [dispatchRequest.bind(this), undefined];chain.unshift.apply(chain, requestInterceptorChain);chain.push.apply(chain, responseInterceptorChain);len = chain.length;promise = Promise.resolve(config);while (i < len) {promise = promise.then(chain[i++], chain[i++]);}return promise;

dispatchRequest则是调用请求的一个方法,其实就是XMLHttpRequest那一套,做了一个适配器的封装,暂不叙述!

所以综合起来看axios就是一个请求接口的一个封装插件,,提供很多方法让你去使用

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

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

相关文章

Linux权限问题(账号切换,权限,粘滞位)

1.什么是权限&#xff1f; 在Linux下有两种用户&#xff0c;分别是超级用户&#xff08;root&#xff09;和普通用户。超级用户可以在Linux下做任何事情&#xff0c;几乎不受限制&#xff0c;而普通用户一般只能在自己的工作目录下&#xff08;/home/xxx&#xff09;工作&#…

暴雨高频交易服务器,解决金融行业痛点

随着计算机技术、大数据、人工智能和通信技术的飞速发展&#xff0c;金融市场的交易方式迎来了革命性变化。交易决策和执行过程自动化、智能化&#xff0c;极大提高了交易效率和速度&#xff0c;推动了金融行业的整体创新和发展。 在技术的不断进步和全球金融市场的数字化转型…

三、Kafka集群

一、Kafka集群的概念 1、目的 高并发、高可用、动态扩展。 主备数据架构、双活节点、灾备数据中心。 如果是服务的地理范围过大也可以使不同的集群节点服务不同的区域&#xff0c;降低网络延迟。 2、Kafka集群的基本概念 1&#xff09;复制&#xff08;镜像&#xff09; kaf…

基于 Transformer 的语言模型

基于 Transformer 的语言模型 Transformer 是一类基于注意力机制&#xff08;Attention&#xff09;的模块化构建的神经网络结构。给定一个序列&#xff0c;Transformer 将一定数量的历史状态和当前状态同时输入&#xff0c;然后进行加权相加。对历史状态和当前状态进行“通盘…

大数据之文件服务器方案

大数据文件服务器方案 一&#xff0c;文件服务器常用框架 二&#xff0c;文件服务器常用框架的实现技术 文件服务器常用框架 文件服务器是一种专门用于存储、管理和共享文件的服务器&#xff0c;其常用框架的实现技术涉及多个方面&#xff0c;以下是一些主要的实现技术及其详…

【刷题15】字符串专题

目录 一、字符串相加二、最长公共前缀三、最长回文子串四、二进制求和五、字符串相乘 一、字符串相加 题目&#xff1a; 思路&#xff1a; 字符串中的每一位的字符转换为数字后要相加&#xff0c;相加的必须是同一位的&#xff0c;即个位加个位&#xff0c;十位加十位。所以…

企业数据安全举报投诉如何有效处理?

相关制度、流程图等获取请联系作者&#xff01;&#xff01; 在当今数字化和信息化的浪潮中&#xff0c;企业数据安全问题越来越受到重视&#xff0c;而对于数据安全的举报和投诉处理是保障企业数据安全、提升用户信任度的重要手段之一。一个完善的举报投诉处理机制能够有效应对…

[综述笔记]Deep learning for brain disorder diagnosis based on fMRI images

论文网址&#xff1a;Deep learning for brain disorder diagnosis based on fMRI images - ScienceDirect 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向…

论文提交步骤 | 2024年第五届MathorCup大数据竞赛

2024年第五届MathorCup数学应用挑战赛—大数据竞赛于2024年10月25日下午6点正式开赛。 论文和承诺书、支撑材料&#xff08;可选&#xff09;及计算结果文档由各参赛队队长电脑登录下方报名主页提交&#xff1a; https://www.saikr.com/vse/bigdata2024 初赛作品提交截止时间为…

[sa-token]StpUtil.getLoginId

闲聊 一般情况下&#xff0c;我们想用uid&#xff0c;可能需要前端将uid传过来&#xff0c;或者将token传来&#xff0c;然后我们进行识别。 用了sa-token之后&#xff0c;可以使用StpUtil.getLoginId()方法获取当前会话的用户id 代码展示 例如以下代码&#xff1a; public Res…

双向 Type-C 转 DP 线:高清视频输出的灵活解决方案

在当今数字化生活中&#xff0c;人们对高效能和高清晰度的需求日益增长。双向 Type-C 转 DP 线应运而生&#xff0c;它以其灵活便捷的特点&#xff0c;为用户提供了一种高清视频输出的解决方案。本文将详细介绍双向 Type-C 转 DP 线的技术原理、适用设备、性能参数以及市场选择…

一键式配置适合 Web 开发的Ubuntu系统

大家好&#xff0c;今天给大家分享一个专为Ubuntu设计的Web开发者配置方案Omakub。 项目介绍 Omakub是一个为开发者打造的、经过精心配置的 Ubuntu 环境项目&#xff0c;由 Ruby on Rails 的创造者 David Heinemeier Hansson&#xff08;DHH&#xff09;发起。目的是为了简化他…

使用WebStorm开发Vue3项目

记录一下使用WebStorm开发Vu3项目时的配置 现在WebStorm可以个人免费使用啦&#xff01;&#x1f929; 基本配置 打包工具&#xff1a;Vite 前端框架&#xff1a;ElementPlus 开发语言&#xff1a;Vue3、TypeScript、Sass 代码检查&#xff1a;ESLint、Prettier IDE&#xf…

【OpenGL】vs中glsl高亮显示插件

vs中glsl高亮显示插件 扩展搜索glsl安装

谷歌CEO劈柴吹了个牛,被自家员工“反诈”

Google的CEO Sundar Pichai&#xff0c;可以说是渲染“AI取代人类”的恐慌氛围的帮凶之一了。 谷歌大部分部门都启用了“AI人力”的策略&#xff0c;进行大规模裁员。与一年前相比&#xff0c;现在谷歌的员工整体数量减少了1112人。 甚至&#xff0c;在最新的公司财报电话会议…

一文了解什么是NLP(自然语言处理)

文章目录 简介NLP 的应用NLP 的工作原理步骤1&#xff1a;文本预处理步骤2&#xff1a;文本表示步骤3&#xff1a;分析和建模 结语主要参考 简介 自然语言处理&#xff08;NLP&#xff09;是一种专业分析人类语言的人工智能。&#xff08;下文皆简称为“NLP”&#xff09;&…

一个基于Zookeeper+Dubbo3+SpringBoot3的完整微服务调用程序示例代码

一、关于 Dubbo3 的一些优化改进介绍 Dubbo3 的官方文档地址&#xff1a; https://cn.dubbo.apache.org/zh-cn/overview/what/overview/ 其针对一些问题进行了优化和改变。个人整理3个小的方面&#xff1a; 1. 在服务注册方面使用 DubboService 注解&#xff0c;不再使用 Servi…

群控系统服务端开发模式-应用开发-上传配置功能开发

下面直接进入上传配置功能开发&#xff0c;废话不多说。 一、创建表 1、语句 CREATE TABLE cluster_control.nc_param_upload (id int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 编号,upload_type tinyint(1) UNSIGNED NOT NULL COMMENT 上传类型 1&#xff1a;本站 2&a…

一:时序数据库-Influx应用

目录 0、版本号 1、登录页面 2、账号基本信息 3、数据库案例 4、可视化 5、java案例 0、版本号 InfluxDB v2.4.0 1、登录页面 http://127.0.0.1:8086/signin 账号&#xff1a;自己账号 密码&#xff1a;自己密码 2、账号基本信息 查看用户id和组织id&#xff01;&…

Linux高阶——1027—进程间关系相关

本章节介绍&#xff0c;进程间的各种关系&#xff1a;亲缘关系&#xff0c;终端进程&#xff0c;进程组&#xff0c;会话&#xff0c;孤儿进程&#xff0c;守护进程 1、亲缘关系 Linux或unix操作系统&#xff0c;进程间具备亲缘关系&#xff0c;分为强亲缘与弱亲缘 强亲缘&a…