当前位置: 首页 > 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);

相关文章:

  • AI驱动商业变革:零售行业的智能化跃迁
  • NOIP2013提高组.货车运输
  • vue,uniapp解决h5跨域问题
  • Linux中的管道
  • UE5有些场景的导航生成失败解决方法
  • PHP使用pandoc把markdown文件转为word
  • C语言超详细结构体知识
  • C++学习:六个月从基础到就业——内存管理:new/delete操作符
  • 如何在 Electron 应用中安全地进行主进程与渲染器进程通信
  • 探索 HumanoidBench:类人机器人学习的新平台
  • 浅谈验证(Verification)和确认(Validation)
  • 【2】CICD持续集成-k8s集群中安装Jenkins
  • 小红书爬虫,小红书api,小红书数据挖掘
  • 在windows上交叉编译opencv供RK3588使用
  • 超导体的应用价值:超导磁探测技术开启科技与生活的新变革
  • 树莓派5+Vosk+python实现语音识别
  • 基于spring boot 集成 deepseek 流式输出 的vue3使用指南
  • 「数据可视化 D3系列」入门第十章:饼图绘制详解与实现
  • 03、GPIO外设(三):标准库代码示例
  • Spring Boot 核心注解全解:@SpringBootApplication背后的三剑客
  • 安徽铁塔回应“指挥调度中心大屏现不雅视频”:将严肃处理
  • 研究|和去年相比,人们使用AI的需求发生了哪些变化?
  • “雷公”起诉人贩子王浩文案开庭:庭审前手写道歉信,庭审中不承认拐走川川
  • 《亡命驾驶》:一场对于男子气概的终极幻想
  • 云南洱源县4.8级地震:房屋受损442户,无人员伤亡报告
  • 俄总理:2024年俄罗斯GDP增长4.3%