基于短轮询的轮询优化

在我们业务中,有很多需要通过轮询去刷新列表状态的场景。在轮询(短轮询)的当前浏览器tab页失活时,列表仍在刷新(发送请求)。这样会给服务器造成很大的压力、浪费带宽和服务器资源,同时前端监控到的某些数据也会失真。
所以在基于短轮询的基础上,通过监听 document 元素的可见性来开启/停止轮询。
失活:切到浏览器的其他tab页、最小化,浏览器窗口被其他app或浏览器窗口完全覆盖。

优化前–轮询

// component.vue
export default {
    data() {
        return {
            timer: null
        }
    },
    methods: {
        startTimer() {
            this.closeTimer()
            this.timer = setInterval(() => {
                this.getTableDate()
            }, 15000)
        },
        closeTimer() {
            clearInterval(this.timer)
        }
    }
}

实现高亮轮询,隐藏时关闭轮询

  1. App.vue 监听浏览器高亮状态
// app.vue
export default {
    mounted() {
        this.init()
    },
    methods: {
    // 监听列表高亮,
       window.addEventListener('visibilitychange', () => {
            this.$store.dispatch('commitDomVisible', document.visibilityState === 'visible')
       }, false)
    }
}
  1. vuex 缓存是否高亮的状态
const common = {
    state: {
        domIsVisible: true
    },
    mutations: {
        setVisible(state, isVisible) {
            state.domIsVisible = isVisible
        }
    }
}
  1. 封装了一个mixin,方便多组件调用
// listPolling.js
export default {
    data() {
        return {
            timer: null,
            isActive: false // 判断组件是否失活,避免在失活时开启组件的轮询
        }
    },
    watch: { // 浏览器窗口可见时开启轮询
        '$store.state.common.domIsVisible': function(val) {
            if (val) {
                this.init()
            } else {
                this.closeTimer()
            }
        }
    },
    activated() {
        this.isActive = true
    },
    // 直接切换菜单栏时执行
    deactivated() {
        this.isActive = false
        this.closeTimer()
    },
    // keep-alive 情况下,路由返回时不会执行 deactivated
    destroyed() {
        this.closeTimer()
    },
    methods: {
        init() {
            if (this.isActive) {
                this.getTableData()
                this.startTimer()
            }
        },
        startTimer() {
            this.closeTimer()
            this.timer = setInterval(() => {
                this.getTableData()
            }, 15000)
        },
        closeTimer() {
            clearInterval(this.timer)
        }
    }
}
  1. 需要轮询的页面调用:
import listPolling from '@/mixins/listPolling'

export default {
    mixins: [listPolling],
    data() {
       return{
         ...
       }
    },
    ...
}

**混入:**当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项

  1. 选项合并:数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
  2. 同名钩子函数将合并为一个数组,因此都将被调用。
  3. 值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。

根据vue 中mixin的特性,我们在某些特殊的轮询组件里,可以自定义轮询时常,开始、结束轮询的时机等。

vue3

// listPolling.js
import {
    ref, watch, onActivated, onDeactivated, onUnmounted, watchEffect
} from 'vue'
import { useWinStore } from '@/stores'

export function useListPolling(getList, pollingInterval = 15000) {
    const timer = ref(null)
    const isActive = ref(false)
    const store = useWinStore()

    const init = () => {
        if (isActive.value) {
            getList()
            startTimer()
        }
    }

    const clearTimer = () => {
        if (timer.value) {
            clearInterval(timer.value)
            timer.value = null
        }
    }
    const startTimer = () => {
        clearTimer()
        timer.value = setInterval(() => {
            getList()
        }, pollingInterval)
    }

    watch(() => store.visibilityState, (val) => {
        console.log('p--watch', val)
        if (val) {
            init()
        } else {
            clearTimer()
        }
    })
    onActivated(() => {
        console.log('p--onActivated')
        isActive.value = true
        init()
    })
    onDeactivated(() => {
        console.log('p--onDeactivated')
        isActive.value = false
        clearTimer()
    })
    return {
        init,
        clearTimer,
        startTimer,
        isActive,
        timer
    }
}
// components.vue
<script setup>
import { useListPolling } from './listPolling'

const { timer, isActive } = useListPolling(getTableData)
</script>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值