当前位置: 首页 > Web前端 > vue.js

axios请求超时,设置重新请求的完美解决方法

时间:2023-03-31 21:24:56 vue.js

自从使用Vue2以来,一直使用官方推荐的axios插件来调用API。在使用过程中,如果服务器或网络不稳定,丢包,怎么办??让我和你分享我的经验。具体原因是最近公司在做一个项目,服务端数据接口使用了Php输出的API,在调用过程中有时会失败,在谷歌浏览器中显示Provisionalheaders。根据搜索引擎给出的解决方案,无法解决我的问题。最近在研究AOP的概念,开发编程的概念。axios开发说明中提到的axios.Interceptors应该就是这样一种降低代码耦合的机制,提高了程序的复用性,同时提高了开发效率。有坑的解决办法——我经验有限,我想我唯一能做的就是在axios请求超时后重新请求。通过研究axios的说明,设置一个timeout=6000axios.defaults.timeout=6000;然后添加一个拦截器。//添加一个请求interceptoraxios.interceptors.request.use(function(config){//在发送请求之前做一些事情returnconfig;},function(error){//做一些请求错误returnPromise.reject(error);});//添加响应interceptoraxios.interceptors.response.use(function(response){//使用响应数据做一些事情returnresponse;},function(error){//使用响应错误做一些事情returnPromise.reject(错误);});这个拦截器的作用是,如果请求超时,拦截器可以捕获信息,然后进行下一步,也就是我要使用重新请求。这是相关页面数据请求。this.$axios.get(url,{params:{load:'noload'}}).then(function(response){//dosomething();}).catch(error=>{//这里超时后捕获错误信息。if(error.response){console.log('error.response')console.log(error.response);}elseif(error.request){console.log(error.request)console.log('error.request')if(error.request.readyState==4&&error.request.status==0){//这里我重新请求}}else{console.log('Error',error.message);}console.log(error.config);});超时后会报Uncaught(inpromise)Error:timeoutofxxxmsexceeded错误。在catch中,它返回了一个error.request错误,所以重试函数就在这里。经测试,可以实现重新请求功能。虽然可以实现超时重请求功能,但是很麻烦,每次请求都需要。API的页面需要设置重新请求。看上面,我的项目有几十个.vue文件,如果每个页面都要设置超时重新请求的功能,那我就疯了。并且这个机制有一个严重的bug,就是当请求的链接失效或者其他原因导致正常访问时,这个机制就失效了。不会等我设置的6秒,一直刷。每秒数十个请求很容易使服务器崩溃。请看下图,眨眼功能,要求146次。第二种有坑的解决方法是研究axios的源码。超时后会在拦截器axios.interceptors.response中抓到错误信息,error.code="ECONNABORTED",具体链接https://github.com/axios/axios/blob/26b06391f831ef98606ec0ed406d2be1742e9850/lib/adapters/xhr.js#L95-L101//Handletimeoutrequest.ontimeout=functionhandleTimeout(){reject(createError('timeoutof'+config.timeout+'msexceeded',config,'ECONNABORTED',request));//清理请求request=null;};所以,我的全局超时重新获取解决方案是这样的。axios.interceptors.response.use(function(response){....},function(error){varoriginalRequest=error.config;if(error.code=='ECONNABORTED'&&error.message.indexOf('timeout')!=-1&&!originalRequest._retry){originalRequest._retry=truereturnaxios.request(originalRequest);}});这个方法也可以实现新的请求,但是有两个问题,1是它只重新请求1次,如果再超时就停止,不会再请求了。第二个问题是我在每个有数据请求的页面上都做了很多操作,比如this.$axios.get(url).then。完成的解决方案是AOP编程方法。我需要的是一个超时重请求的全局函数。我需要在axios.Interceptors上下功夫。在github上axios的issue中找了一些别人的解决方案,终于找到了完整的解决方案。,如下。https://github.com/axios/axios/issues/164#issuecomment-327837467//在main.js设置全部的请求次数,请求的间隔axios.defaults.retry=4;axios.defaults.retryDelay=1000;axios.interceptors.response.use(undefined,functionaxiosRetryInterceptor(err){varconfig=err.config;//如果config不存在或者没有设置重试选项,则拒绝if(!config||!config.retry)returnPromise.reject(err);//设置用于跟踪重试计数的变量config.__retryCount=config.__retryCount||0;//检查我们是否已经达到重试总数的上限if(config.__retryCount>=config.retry){//拒绝并返回错误returnPromise.reject(err);}//增加重试次数config.__retryCount+=1;//创建新的promise来处理指数退避varbackoff=newPromise(function(resolve){setTimeout(function(){resolve();},config.retryDelay||1);});//返回承诺其中调用axios重试请求returnbackoff.then(function(){returnaxios(config);});});几十个.vue页面的this.$axios的get和post方法都是基础的,不需要修改他们的代码下面是我做的一个实验。.设置axios.defaults.retryDelay=500,照常要求www.facebook.com提供源码。如果您有更好的建议,请告诉我,谢谢。http://github.com/ssttm169/use-axios-well