记录:切换后台时,JS定时器被暂停的处理方案

0 阅读2分钟

问题场景

测试同事反馈:

操作是12分的时候将app停留在这个页面然后后台了;

等15分的时候再次打开app还是这个页面。

然后倒计时显示仍旧是在当时切出去后台页面的倒计时开始继续计算

企业微信截图_17732170262497.png

然后我想,是不是切出后台的时候,部分手机系统出于节能的原因暂停了JS计时器(我在iOS没遇到,只在安卓复现出来)。

为了验证这一猜想,我画了一个页面,里面只有计时器。

接着,我分别在我机子、测试同事的机子进行测试,验证了这个猜想。

解决的方案(询问ai哈哈):

方案一、修改定时器写法

原先是调接口获取到倒数时间(秒),定时器每秒减1。

如何修改?

获取结束的时间戳,针对定时器暂停,在每次返回页面的时候,需要获取当前时间时间戳,重新计算剩余时间,然后继续倒计时每秒减1。

采用时间戳校准法,不单纯依赖 setInterval 的累减,而是记录目标结束时间,每次刷新时计算剩余时间。

image.png

image.png

方案二、监听是否切换后台,在重返页面的时候重新调接口校准倒计时

浏览器提供了 visibilitychange 事件来监听页面可见性变化:

document.visibilityState 返回 'visible'(前台)或 'hidden'(后台)

image.png

END~thx

代码片段

mounted () {
    // 监听页面可见性变化
    document.addEventListener('visibilitychange', this.handleVisibilityChange)
  },
  beforeDestroy () {
    // 组件销毁前清除定时器
    this.stopCountdown()
    // 移除监听器
    document.removeEventListener('visibilitychange', this.handleVisibilityChange)
  },
  methods: {
    handleVisibilityChange () {
      if (document.visibilityState === 'visible') {
        // 页面回到前台,校准倒计时
        console.log('页面回到前台,校准倒计时')
      } else {
        // 页面进入后台,可选暂停定时器节省资源
        // this.stopCountdown()
        console.log('页面进入后台,暂停定时器节省资源')
      }
    },
    startCountdown () {
      // 初始化结束时间戳
      // 切换到后台时,安卓手机端会自动暂停定时器,需要重新计算倒计时时间
      this.endTime = Date.now() + this.countdown * 1000

      this.countdownInterval = setInterval(() => {
        const now = Date.now() // 重新返回页面时获取当前时间戳,计算剩余时间
        const remaining = Math.floor((this.endTime - now) / 1000)

        if (remaining > 0) {
          this.countdown = remaining
        } else {
          this.countdown = 0
          this.stopCountdown()
        }
      }, 1000)
    },