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

axios 模拟实现

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;}elsereject({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;}elsereject({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.xdnf.cn/news/8209.html

相关文章:

  • 【HFP】蓝牙HFP协议音频连接核心技术深度解析
  • 【2】CICD持续集成-k8s集群中安装Jenkins
  • 8.观察者模式:思考与解读
  • 【SAP ME 44】在 HANA DB中报废SFC时的SHOP_ORDER表记录锁定
  • 设计模式从入门到精通之(五)观察者模式
  • LIB-ZC, 一个跨平台(Linux)平台通用C/C++扩展库, stream 流操作
  • conversation_template | conversation_actors | conversation_line_template
  • 网安加·百家讲坛 | 刘志诚:AI安全风险与未来展望
  • MCP的推出将给未来的开发带来哪些变革?
  • 解决jupyter notebook修改路径下没有c.NotebookApp.notebook_dir【建议收藏】
  • 第五章 SQLite数据库:4、SQLite 进阶用法:常见的约束、PRAGMA 配置、数据操作
  • 2025年03月中国电子学会青少年软件编程(Python)等级考试试卷(二级)真题
  • 《软件设计师》复习笔记(4.2)——关系代数、函数依赖、范式
  • 下载HBuilder X,使用uniapp编写微信小程序
  • Linux简介
  • 下拉框select标签类型
  • PLOS ONE:VR 游戏扫描揭示了 ADHD 儿童独特的大脑活动
  • 基础数学知识-概率论
  • 机器学习05-CNN
  • 守护进程及gdb调试(新手简略版)
  • 工作总结(十二)——迁移svn单项目到gitlab上,保留历史提交记录
  • 02.Spring_IOC详解
  • Evidential Deep Learning和证据理论教材的区别(主要是概念)
  • test ssl java
  • 【C++指南】哈希驱动的封装:如何让unordered_map/set飞得更快更稳?【上】
  • 数据结构学习笔记 :二叉搜索树与高效查找算法详解
  • React 列表渲染基础示例
  • DFS/BFS专练-搞定图论基础!(从海岛问题过渡至图论基础应用C++/C)
  • 无刷电机槽数相同、转子极数不同的核心区别
  • Nacos安装及数据持久化