axios 模拟实现

news2025/4/19 17:51:28

axios 模拟实现

包含发送请求,拦截器,取消请求

第一步 , axios模拟发送请求

            //使用 xhr 发送请求
            function xhr_adpter(config){
                return new Promise(function handle(resolve,reject){
                    let xhr = new XMLHttpRequest();
                    xhr.open(config.method, config.url,true);

                    xhr.onreadystatechange = function(){
                        if(4 === xhr.readyState){
                            
                            // 成功, 携带对应数据
                            if(xhr.status >= 200 && xhr.status < 300){
                                resolve({
                                    config,
                                    data:xhr.response,
                                    status:xhr.status,
                                    headers:xhr.getAllResponseHeaders(),
                                    request:xhr
                                });
                                return;
                            }
                            else
                                reject({
                                    data:xhr.response,
                                    status : xhr.status
                                });
                        }
                    }
                    //只考虑Get情况
                    xhr.send();
                });
            }
            
			// 使用http还是xhr,这里省略http发送请求
            function dispatch_req(config){
                /*
                    判断使用 http or xhr
                    这里只模拟xhr
                */
                return xhr_adpter(config).then(res=>{
                    // 对响应结果做转化,这里省略转化过程,直接返回结果
                    return res;
                },error=>{
                    throw error;
                })
            } 
              
			// 模拟实现,暂不使用
            function Axios(config){
                this.config = config;
            }
			
			// 请求函数
            Axios.prototype.request = function(config){
                let promise = Promise.resolve(config);
                
                //为下面的拦截器做铺垫
                let callbacks = [dispatch_req, null] ;
                return  promise.then(callbacks[0],callbacks[1]);
            }
			
			// 仅模拟
            let context = new Axios({});

            //绑定上下文, axios() 相当于 request()
            let axios = Axios.prototype.request.bind(context);

            let new_promise = axios({method:"GET",url:"http://127.0.0.1/get_axios"});
            new_promise.then(res=>{
                console.log("get :", res);                
            },error=>{
                console.log("error:",error)
            });

第二步,拦截器模拟

添加拦截器函数
	 //拦截器
            function Interceptor(){
                this.handlers = [];
            }

            Interceptor.prototype.use = function(success=null, fail=null){
                this.handlers.push(
                    {
                        success,
                        fail
                    }
                );
            }

构造函数新增拦截器
		function Axios(config){
                this.config = config;

                //新增拦截器
                this.interceptors = {
                    request: new Interceptor(),
                    response : new Interceptor()
                };
            }
新增初始化函数
	function prepare(){

		let context = new Axios({});
		
	   //绑定上下文, axios() 相当于 request()
	    let axios = Axios.prototype.request.bind(context);
	
	    //增加拦截器引用属性到axios, 以方便使用
	    Object.keys(context).forEach(key=>{
	        axios[key] = context[key];
	    });
	
	
	    return axios;
	}
修改请求函数
 // 请求函数
            Axios.prototype.request = function(config){
                let promise = Promise.resolve(config);

                // 保存所有回调,包含拦截器, 形成then回调
                let callbacks = [dispatch_req, null] ;
                
                /*
                    把拦截器加入数组
                    把请求拦截器 放入数组前端
                    把响应拦截器 放入数组后面
                    整个数组像这样:
                    [请求拦截success回调,请求拦截fail回调, dispatch_req,null, 响应拦截success,响应拦截fail] 
                */
                while(this.interceptors.request.handlers.length > 0){
                    let handler = this.interceptors.request.handlers.shift();
                    callbacks.unshift(handler.success, handler.fail);
                }
                    

                while(this.interceptors.response.handlers.length > 0){
                    let handler = this.interceptors.response.handlers.shift();
                    callbacks.push(handler.success, handler.fail)
                }
                    
                // 为数组回调生成所有promise对象
                while(callbacks.length > 0){
                    let success = callbacks.shift();
                    let fail = callbacks.shift();
                    promise = promise.then(success,fail);
                }

                return promise;
            }

拦截器完整代码

			//拦截器
            function Interceptor(){
                this.handlers = [];
            }

            Interceptor.prototype.use = function(success=null, fail=null){
                this.handlers.push(
                    {
                        success,
                        fail
                    }
                );
            }



            //使用 xhr 发送请求
            function xhr_adpter(config){
                return new Promise(function handle(resolve,reject){
                    let xhr = new XMLHttpRequest();
                    xhr.open(config.method, config.url,true);

                    xhr.onreadystatechange = function(){
                        if(4 === xhr.readyState){
                            
                            // 成功, 携带对应数据
                            if(xhr.status >= 200 && xhr.status < 300){
                                resolve({
                                    config,
                                    data:xhr.response,
                                    status:xhr.status,
                                    headers:xhr.getAllResponseHeaders(),
                                    request:xhr
                                });
                                return;
                            }
                            else
                                reject({
                                    data:xhr.response,
                                    status : xhr.status
                                });
                        }
                    }
                    //只考虑Get情况
                    xhr.send();
                });
            }

            function dispatch_req(config){
                /*
                    判断使用 http or xhr
                */
                return xhr_adpter(config).then(res=>{
                    // 对响应结果做转化,这里省略转化过程,直接返回结果
                    return res;
                },error=>{
                    throw error;
                })
            }   

            function Axios(config){
                this.config = config;

                //新增拦截器
                this.interceptors = {
                    request: new Interceptor(),
                    response : new Interceptor()
                };
            }


            // 请求函数
            Axios.prototype.request = function(config){
                let promise = Promise.resolve(config);

                // 保存所有回调,包含拦截器, 形成then回调
                let callbacks = [dispatch_req, null] ;
                
                /*
                    把拦截器加入数组
                    把请求拦截器 放入数组前端
                    把响应拦截器 放入数组后面
                    整个数组像这样:
                    [请求拦截success回调,请求拦截fail回调, dispatch_req,null, 响应拦截success,响应拦截fail] 
                */
                while(this.interceptors.request.handlers.length > 0){
                    let handler = this.interceptors.request.handlers.shift();
                    callbacks.unshift(handler.success, handler.fail);
                }
                    

                while(this.interceptors.response.handlers.length > 0){
                    let handler = this.interceptors.response.handlers.shift();
                    callbacks.push(handler.success, handler.fail)
                }
                    
                // 为数组回调生成所有promise对象
                while(callbacks.length > 0){
                    let success = callbacks.shift();
                    let fail = callbacks.shift();
                    promise = promise.then(success,fail);
                }

                return promise;
            }

            // 初始化函数
            function prepare(){

                let context = new Axios({});

                //绑定上下文, axios() 相当于 request()
                let axios = Axios.prototype.request.bind(context);

                //增加拦截器引用属性到axios, 以方便使用
                Object.keys(context).forEach(key=>{
                    axios[key] = context[key];
                });


                return axios;
            }

            axios = prepare();
            axios.interceptors.request.use(config=>{
                console.log("请求1",config)
                return config;
            },error=>{});

            axios.interceptors.request.use(config=>{
                console.log("请求2",config)
                return config;
            },error=>{});
            

            axios.interceptors.response.use(res=>{
                console.log("响应1");
                return res;
            });
            axios.interceptors.response.use(res=>{
                console.log("响应2");
                return res;
            });
            
            

            let new_promise = axios({method:"GET",url:"http://127.0.0.1/get_axios"});
            new_promise.then(res=>{
                console.log("get :", res);                
            },error=>{
                console.log("error:",error)
            });

            

添加取消请求

代码较为简单,只贴出新增代码
	 		//取消请求
            function AbortSignal(){
                // 此promise的状态由外部调用
                let resolve_func;
                this.promise = new Promise(resolve=>{
                    resolve_func = resolve;
                });

                //添加abort函数,外部可直接调用
                this.abort = resolve_func;
            }
在xhr发送请求的代码中添加 取消请求的处理
//使用 xhr 发送请求
            function xhr_adpter(config){
                return new Promise(function handle(resolve,reject){
                    let xhr = new XMLHttpRequest();
                    xhr.open(config.method, config.url,true);

                    // 若配置对象中有signal属性
                    if(config.signal){
                        config.signal.promise.then(res=>{
                            xhr.abort();
                        });
                    }
					
					/*
						以下代码不变
					*/

                });
            }
			//创建一个取消请求的对象
			let abort_signal = new AbortSignal();
			
            let new_promise = axios({
                method:"GET",
                url:"http://127.0.0.1/get_axios",
                signal: abort_signal	//新增部分
            });
            new_promise.then(res=>{
                console.log("get :", res);                
            },error=>{
                console.log("error:",error)
            });

            setTimeout(() => {
                abort_signal.abort();
            }, 1000);

	

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

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

相关文章

OpenAI重返巅峰:o3与o4-mini引领AI推理新时代

引言 2025年4月16日&#xff0c;OpenAI发布了全新的o系列推理模型&#xff1a;o3和o4-mini&#xff0c;这两款模型被官方称为“迎今为止最智能、最强大的大语言模型&#xff08;LLM&#xff09;”。它们不仅在AI推理能力上实现了质的飞跃&#xff0c;更首次具备了全面的工具使…

Unity3d 6(6000.*.*)版本国区下载安装参考

前言 Unity3d 6.是最新的版本&#xff0c;是与来自世界各地的开发者合作构建、测试和优化的成果&#xff0c;现在可以完全投入生产&#xff0c;是我们迄今为止性能最出色、最稳定的 Unity 版本。Unity 6 有许多令人兴奋的新工具和功能&#xff1a;端到端多人游戏工作流程将加速…

第 3 期:逆过程建模与神经网络的作用(Reverse Process)

一、从正向扩散到逆向去噪&#xff1a;生成的本质 在上期中我们讲到&#xff0c;正向扩散是一个逐步加入噪声的过程&#xff0c;从原始图像 x_0到接近高斯分布的 x_T​&#xff1a; 而我们真正关心的&#xff0c;是从纯噪声中逐步还原原图的过程&#xff0c;也就是逆过程&…

健康养生:开启活力生活新篇章

在当代社会&#xff0c;熬夜加班、久坐不动、外卖快餐成为许多人的生活常态&#xff0c;随之而来的是各种亚健康问题。想要摆脱身体的疲惫与不适&#xff0c;健康养生迫在眉睫&#xff0c;它是重获活力、拥抱美好生活的关键。​ 应对不良饮食习惯带来的健康隐患&#xff0c;饮…

记录学习的第二十九天

还是力扣每日一题。 本来想着像昨天一样两个循环搞定的&#xff0c;就下面&#x1f447;&#x1f3fb; 不过&#xff0c;结果肯定是超时啦&#xff0c;中等题是吧。 正确答案是上面的。 之后就做了ls题单第一部分&#xff0c;首先是定长滑窗问题 这种题都是有套路的&#xff0…

Express学习笔记(六)——前后端的身份认证

目录 1. Web 开发模式 1.1 服务端渲染的 Web 开发模式 1.2 服务端渲染的优缺点 1.3 前后端分离的 Web 开发模式 1.4 前后端分离的优缺点 1.5 如何选择 Web 开发模式 2. 身份认证 2.1 什么是身份认证 2.2 为什么需要身份认证 2.3 不同开发模式下的身份认证 3. Sessio…

leetcode 309. Best Time to Buy and Sell Stock with Cooldown

目录 题目描述 第一步&#xff0c;明确并理解dp数组及下标的含义 第二步&#xff0c;分析并理解递推公式 1.求dp[i][0] 2.求dp[i][1] 3.求dp[i][2] 第三步&#xff0c;理解dp数组如何初始化 第四步&#xff0c;理解遍历顺序 代码 题目描述 这道题与第122题的区别就是卖…

优化自旋锁的实现

在《C11实现一个自旋锁》介绍了分别使用TAS和CAS算法实现自旋锁的方案&#xff0c;以及它们的优缺点。TAS算法虽然实现简单&#xff0c;但是因为每次自旋时都要导致一场内存总线流量风暴&#xff0c;对全局系统影响很大&#xff0c;一般都要对它进行优化&#xff0c;以降低对全…

SS25001-多路复用开关板

1 概述 1.1 简介 多路复用开关板是使用信号继电器实现2线制的多路复用开关板卡&#xff1b;多路复用开关是一种可以将一个输入连接到多个输出或一个输出连接到多个输入的拓扑结构。这种拓扑通常用于扫描&#xff0c;适合将一系列通道自动连接到公共线路的的设备。多路复用开…

【AI News | 20250418】每日AI进展

AI Repos 1、exa-mcp-server AI助手通过Exa获得实时网络信息获取的能力&#xff0c;提供结构化的搜索结果&#xff0c;返回包括标题、URL以及内容片段在内的结构化结果&#xff1b;会把最近的搜索结果缓存为资源&#xff0c;下次再搜索相同的内容时可以直接使用缓存&#xff1…

Dify LLM大模型参数(一)

深入了解大语言模型&#xff08;LLM&#xff09;的参数设置 模型的参数对模型的输出效果有着至关重要的影响。不同的模型会拥有不同的参数&#xff0c;而这些参数的设置将直接影响模型的生成结果。以下是 DeepSeek 模型参数的详细介绍&#xff1a; 温度&#xff08;Tempera…

展示数据可视化的魅力,如何通过图表、动画等形式让数据说话

在当今信息爆炸的时代&#xff0c;数据的量级和复杂性不断增加。如何从海量数据中提取有价值的信息&#xff0c;并将其有效地传达给用户&#xff0c;成为了一个重要的课题。数据可视化作为一种将复杂数据转化为直观图形、图表和动画的技术&#xff0c;能够帮助用户快速理解数据…

时序预测 | Matlab实现基于VMD-WOA-ELM和VMD-ELM变分模态分解结合鲸鱼算法优化极限学习机时间序列预测

时序预测 | Matlab实现基于VMD-WOA-ELM和VMD-ELM变分模态分解结合鲸鱼算法优化极限学习机时间序列预测 目录 时序预测 | Matlab实现基于VMD-WOA-ELM和VMD-ELM变分模态分解结合鲸鱼算法优化极限学习机时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab…

基于EasyX库开发的球球大作战游戏

目录 球球大作战 一、开发环境 二、流程图预览 三、代码逻辑 1、初始化时间 2、设置开始界面大小 3、设置开始界面 4、让玩家选择速度 5、设置玩家小球、人机小球、食物的属性 6、一次性把图绘制到界面里 7、进入死循环 8、移动玩家小球 9、移动人机 10、食物刷新…

《系统分析师-第三阶段—总结(一)》

背景 采用三遍读书法进行阅读&#xff0c;此阶段是第三遍。 过程 第一章 第二章 总结 在这个过程中&#xff0c;对导图的规范越来越清楚&#xff0c;开始结构化&#xff0c;找关系&#xff0c;找联系。

AI——K近邻算法

文章目录 一、什么是K近邻算法二、KNN算法流程总结三、Scikit-learn工具1、安装2、导入3、简单使用 三、距离度量1、欧式距离2、曼哈顿距离3、切比雪夫距离4、闵可夫斯基距离5、K值的选择6、KD树 一、什么是K近邻算法 如果一个样本在特征空间中的k个最相似&#xff08;即特征空…

用 NLP + Streamlit,把问卷变成能说话的反馈

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

TCP/IP和UDP协议的发展历程

TCP/IP和UDP协议的发展历程 引言 互联网的发展史是人类技术创新的辉煌篇章&#xff0c;而在这一发展过程中&#xff0c;通信协议发挥了奠基性的作用。TCP/IP&#xff08;传输控制协议/互联网协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;作为互联网通信的基础…

Function Calling的时序图(含示例)

&#x1f9cd; 用户&#xff1a; 发起请求&#xff0c;输入 prompt&#xff08;比如&#xff1a;“请告诉我北京的天气”&#xff09;。 &#x1f7ea; 应用&#xff1a; 将用户输入的 prompt 和函数定义&#xff08;包括函数名、参数结构等&#xff09;一起发给 OpenAI。 …

若依框架修改左侧菜单栏默认选中颜色

1.variables.sacc中修改为想要的颜色 2.给目标设置使用的颜色