vue路由切换时取消之前的所有请求操作
在main.js文件里
importrouterfrom'router/'; importVuefrom'vue'; Vue.Cancel=[]; router.beforeEach((to,from,next)=>{ while(Vue.Cancel.length>0){ Vue.Cancel.shift()('cancel'); } next(); })
ajax文件
importVuefrom'vue'; importaxiosfrom'axios'; importVueAxiosfrom'vue-axios'; Vue.use(VueAxios,axios); //导入封装的回调函数 import{ cbs, gbs }from'config/'; //动态设置本地和线上接口域名 Vue.axios.defaults.baseURL=gbs.host; /** *封装axios的通用请求 *@param{string}typeget或post *@param{string}url请求的接口URL *@param{object}data传的参数,没有则传空对象 *@param{object}urlParamsurl传参 *@param{Function}fn回调函数 *@param{boolean}tokenFlag是否需要携带token参数,为true,不需要;false,需要。一般除了登录,都需要 */ exportdefaultfunction({ type, path, data, params, urlParams, fn, errFn, tokenFlag, headers, opts }={}){ varoptions={ method:type, url:path, params:params, headers:headers&&typeofheaders==='object'?headers:{}, cancelToken:newaxios.CancelToken(function(cancel){ Vue.Cancel&&Vue.Cancel.push(cancel) }) }; //检测接口权限 varapi_flag=true; if(options.url&&options.url.indexOf(gbs.host)&&this.$store.state.user.userinfo.access_status===1){ varurl=options.url.replace(gbs.host,''); varapi_routers=this.$store.state.user.userinfo.api_routers; if(!api_routers||!api_routers.constructor===Object||!api_routers[url]){ api_flag=false; } } varurlParamsArray=[]; if(api_flag===true){ options[type==='get'?'params':'data']=data; //用于url传参 if(typeof(urlParams)=="object"){ for(varkinurlParams){ urlParamsArray.push(k+'='+urlParams[k]) } options.url+='?'+urlParamsArray.join('&'); } if(typeof(urlParams)=="string"||typeof(urlParams)=="number"){ options.url+=urlParams; } if(options.url.indexOf('?')>-1){ options.url+='&_='+(newDate()).getTime(); }else{ options.url+='?_='+(newDate()).getTime(); } //分发显示加载样式任务 this.$store.dispatch('show_loading'); if(tokenFlag!==true){ //如果你们的后台不会接受headers里面的参数,打开这个注释,即实现token通过普通参数方式传 //data.token=this.$store.state.user.userinfo.token; options.headers.token=this.$store.state.user.userinfo.token; } //扩展Promise使支持finally(),用了babel就不用手写了^.^ //Promise.prototype.finally=function(callback){ //letPromise=this.constructor; //returnthis.then( //value=>Promise.resolve(callback()).then(()=>value), //reason=>Promise.resolve(callback()).then(()=>{throwreason}) //); //}; //发送请求 returnnewPromise((resolve,reject)=>{ Vue.axios(options).then((res)=>{ this.$store.dispatch('hide_loading'); if(res.data[gbs.api_status_key_field]===gbs.api_status_value_field||(res.status===gbs.api_status_value_field&&!res.data[gbs.api_status_key_field])){ fn(res.data); }else{ if(gbs.api_custom[res.data[gbs.api_status_key_field]]){ gbs.api_custom[res.data[gbs.api_status_key_field]].call(this,res.data); }else{ cbs.statusError.call(this,res.data); if(errFn){ errFn.call(this,res.data); } } } resolve(res.data); }).catch((err)=>{ if(err.response&&err.response.status!==403){ try{ errFn?errFn.call(this,this.$$lib__.isObject(err.response.data)?err.response.data:{}):null; }catch(err){ console.error(err.message); } } if(err.response&&err.response.data===''){ cbs.statusError.call(this,{status:err.response.status}); }elseif(err.response&&this.$$lib__.isObject(err.response.data)){ cbs.statusError.call(this,err.response.data); }elseif(err.response){ cbs.requestError.call(this,err); }else{ console.error('Errorfrom','"'+path+'".',err.message); } reject(err); }); }); }else{ this.$alert('您没有权限请求该接口!','请求错误',{ confirmButtonText:'确定', type:'warning' }); } };
核心代码为cancelToken参数
varoptions={ method:type, url:path, params:params, headers:headers&&typeofheaders==='object'?headers:{}, cancelToken:newaxios.CancelToken(function(cancel){ Vue.Cancel&&Vue.Cancel.push(cancel) }) };
补充知识:problem:vue组件局部刷新,在组件销毁(destroyed)时取消刷新无效问题
场景:
一个群发消息列表(数组)
列表下有多条消息(元素)
每条正在发送的消息数据状态需要实时刷新,发送完成时需要显示成功提示符合且不需要刷新,然后3秒消失。首次显示列表时,已经成功的状态不显示这个成功提示符。
1、定位确定采用局部刷新
2、进入消息列表请求获取列表数据的接口,完成发送的消息不需显示完成状态
3、正在发送的消息首次渲染时就调用setTimeout轮询刷新当前消息的接口,完成时,显示完成状态(新增一个完成状态的字段)
4、页面销毁时,还在发送的消息也取消刷新
误区:
1、每条消息没有抽成一个单独的组件,想要首次渲染组件调用刷新接口时,只能通过定义全局map变量来映射每条消息的刷新接口的定时器,明显增加业务开发的复杂度,增加了一些不确定性的bug风险。
每条消息抽成组件之后,就可以在组件中的mounted中去调用刷新的接口,页面销毁时取消刷新可以在destroyed里面去销毁。
2、这里的一个误区是在destroyed里面去清除定时器的id,导致调用了destroyed钩子刷新的定时器还是无法清除。将定时器id当做一个属性值存在了每条数据所属的对象中,然后在子组件(每条消息所属的)中的destroyed中去读取该对象的当前的定时器属性,因为读出来是undifined,其实并没有拿到当前消息正在执行的定时器,所以清除不掉。
组件使用有误,每一个组件都是一个独立的元素,其中定义的变量也是私有的,定时器id定在当前组件的data中就可以了,不需要再在数组中的每一条消息中定一个专属的定时器id。
抽象出来的简单版刷新数据,5秒后取消刷新。
letintervalId=null functioninit(){ this.refresh() } functionrefresh(){ intervalId=setTimeout(()=>{ this.getRefreshData() },2000); } functiongetRefreshData(){ console.log('startgetdata.....',intervalId) setTimeout(()=>{ console.log('getdata.....') this.refresh() },100); } functionstopRefresh(){ console.log('stop....',intervalId) clearInterval(intervalId) } this.init() setTimeout(()=>{ this.stopRefresh() },5000);
以上这篇vue路由切换时取消之前的所有请求操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。