vue axios+定时器实现1秒实时数据刷新 页面关闭后上一个页面定时器访问的pending请求,在vue实例销毁时关闭定时器以及pending中的请求

3 篇文章 0 订阅
1 篇文章 0 订阅
项目当中列表查看目标云主机的监控,页面当中以定时器内每一秒发出一次请求方式来实现实时刷新数据,当点击列表选项卡后,监控页面刷新数据的axios请求有pending状态,此时在列表页(即父页面)会弹出监控页面(即子页面)的弹框,实现目标:即在监控页面切换到列表页面时,关闭监控页面的定时器和pending状态请求。

会遇到的问题:

  1. 当打开监控页面接口正常的时候,定时器正常运行,点击切换列表页后pending的请求完成,在列表页会继续执行后续逻辑,找不到对应的就会报错,即走到服务器错误弹出框,因此会在此时弹出n个框。*************解决办法:在页面销毁的时候将定时器关闭,在axios请求头加上官网文档介绍的关闭pending请求的东西,并在销毁实例的生命周期函数当中将其关闭,并将axios.catch(){}中的代码加上try{}catch(res){}
  2. 我在axios报错的时候捕获异常,弹框后跳转列表页当中,此时因为前几个pending的请求可能会导致定时器比第一个请求报错需要执行的逻辑代码要快,即在顶一个请求还未做出反应的时候,定时器可能已经执行多个axios请求,所以依然会在切换到列表页弹出多个框。***************解决办法:axios请求报错之后就需要进行定时器关闭、取消pending请求和重置定时器。然后在data中定义一个执行标记,在弹框之前进行判断此标记并在判断内第一行执行标记取反,后续再执行弹框

这样的结局办法页面当中可以解决,页面上虽然看不出来,但是可以请求还是会多出几个来,数据量非常庞大的情况下也不建议使用定时器这样的方式来进行实时数据刷新(我这块的数据量没有非常多),数据量大想要实现页面数据实时刷新,建议使用websocket和后台进行长连接,在实例销毁时关闭长连接即可,也不会出现这篇博文的情况。

data数据定义

data (){
	return {
		intervalTimer:null,//定时器
        axiosFlag:true//catch中的弹框标记
	}
}

方法、生命周期函数

destroyed (){
    clearInterval(this.intervalTimer)//关闭定时器
    this.intervalTimer=null  //重置定时器
},
mounted (){
	this.initTable();
},
methods:{
	initTable(){
		var _this=this
        let CancelToken = _this.$axios.CancelToken
        _this.axiosFlag=true//刷新页面将此标记重置
         _this.intervalTimer=setInterval(function(){//定时调用接口
            _this.$axios.get(`/api/monitor/detail/${_this.serviceStatus.id}`, {
                cancelToken: new CancelToken(function executor(c) {//axios自带关闭请求方法
                    _this.cancel = c
                    // console.log(c)
                    // 这个参数 c 就是CancelToken构造函数里面自带的取消请求的函数,这里把该函数当参数用
                })
            }).then(res => {
                if(res.status === 200){
                    //处理页面加载需要的数据
                    _this.info=res.data
                    _this.loadDiskUsage()
                    _this.loadMemoryUsage()
                }
            }).catch(res => {
                try{//捕获异常(在接口请求不报错的情况下,点击列表页还会出现弹框,因为pending完成之后请求找不到对应的字段,这时候只需要try catch 捕获异常即可)
                    _this.cancel()//取消pending中的请求
                    clearInterval(_this.intervalTimer) //关闭定时器
                    _this.intervalTimer=null //重置定时器
                    if(res.response.status === 500 || res.response.status === 404 || res.response.status === 504){
                        if(_this.axiosFlag){//报错后是否弹窗标记,
                            _this.axiosFlag=false
                            _this.$message({
                                message: '系统错误,请重新查看!',
                                type: 'error',
                                onClose:res =>{
                                    _this.$router.push('serviceStatus')
                                }
                            });
                        }
                    }
                }catch(res){
                    // console.log(res)
                }
                
            })                    
        },1000)
	}
}

2020/5/6 vuex存储请求路由跳转利用cancelToken来关闭上一个页面的请求

main.js

// 添加请求拦截器,在请求头中加token
axios.interceptors.request.use(config => {
  config.cancelToken = new axios.CancelToken(function (cancel) {
    store.commit('pushToken', {cancelToken: cancel})
  })
  return config;
}, error => {
// 对请求错误做些什么
  return Promise.reject(error);
});

state.js

let cancelTokenArr=[]
export default {
    cancelTokenArr
}

mutations.js

export default{
	pushToken (state, payload) {
        state.cancelTokenArr.push(payload.cancelToken)
    },
    clearToken (state) {
        state.cancelTokenArr.forEach(item => {
            item('路由跳转取消上一页的请求')
        })
        state.cancelTokenArr = []
    }
 }

router.js(next() 之前进行 清空store中的pending请求数组 达到关闭正在pending的请求 抛出异常)

// 配置路由权限
router.beforeEach((to, from, next) => {
    let getTokenPath=to.path
    // console.log(to.path)
    if(getTokenPath === '/single_sign_on'){//判断是否是固定的权限访问授权路由
        let token = to.query.token
        let appid = to.query.appid
        if(token){
            // 通过 token 访问第三方api 获取有效key进入首页并将key存入localstorage 否则进入login
            axios.get('/inapi/login/index',{
                headers:{
                    token:token,
                    appid:appid
                }}).then(res => {
                    if(res.data.code === 0){
                        store.commit('set_xaiot_token_key',res.data.data.role)
                        store.commit('set_xaiot_token',token)
                        store.commit('set_username',res.data.data.role)
                        store.commit('clearToken')
                        next('/')
                    }else{
                        localStorage.clear()
                        sessionStorage.clear()
                        store.commit('clearToken')
                        next('/login')
                    }
            }).catch(res => {
                // console.log(res.data.msg,'error')
                localStorage.clear()
                sessionStorage.clear()
                store.commit('clearToken')
                next('/login')
            })
        }else{
            localStorage.clear()
            sessionStorage.clear()
            store.commit('clearToken')
            next('/login')
        }
    }
    let xaiot_token=store.state.xaiot_token
    if (to.meta.requireAuth) { // 判断该路由是否需要登录权限
        if (xaiot_token) { // 判断本地是否存在access_token
          store.commit('clearToken')
            next()
        } else {
            // 未登录,跳转到登陆页面,并且带上 将要去的地址,方便登陆后跳转。
            localStorage.clear()
            sessionStorage.clear()
            store.commit('clearToken')
            next('/login')
        }
    } else {
      store.commit('clearToken')
        next()
    }
  })
export default router
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你可以使用Vue3定时器函数`setInterval()`来实现这个功能。首先,在你的页面一个下拉框,使用`v-model`来绑一个data属性,用于记录选择的定时器: ```html <template> <div> <select v-model="selectedTimer"> <option value="10">10</option> <option value="20">20</option> <option value="30">30</option> </select> </div> </template> ``` 然后,在`mounted()`钩子函数初始化定时器,根据选择的定时器间设置定时器的间隔,并在定时器回调函数执行刷新操作: ```javascript <script> export default { data() { return { selectedTimer: '10', // 默认选择10 } }, mounted() { setInterval(() => { const interval = parseInt(this.selectedTimer) * 1000 // 转换为毫 console.log(`每${this.selectedTimer}刷新页面`) // 执行刷新操作 }, parseInt(this.selectedTimer) * 1000) } } </script> ``` 需要注意的是,如果用户在下拉框选择了一个不同的定时器间,你需要清除当前的定时器并重新初始化新的定时器,可以使用`clearInterval()`函数来清除定时器。可以在`watch`选项监听`selectedTimer`属性的变化: ```javascript <script> export default { data() { return { selectedTimer: '10', // 默认选择10 timerId: null, // 用于记录当前定时器的ID } }, mounted() { this.initTimer() }, methods: { initTimer() { this.timerId = setInterval(() => { const interval = parseInt(this.selectedTimer) * 1000 // 转换为毫 console.log(`每${this.selectedTimer}刷新页面`) // 执行刷新操作 }, parseInt(this.selectedTimer) * 1000) } }, watch: { selectedTimer(newValue, oldValue) { clearInterval(this.timerId) this.initTimer() } } } </script> ``` 这样就可以实现根据下拉框选择执行对应定时器的功能了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值