解决ios 倒计时在退出应用出现暂停状态

325 阅读2分钟

一、背景

要实现一个倒计时页面,如下图:

93c1521e-4846-4c77-bf39-53c085e933d5.jpg

服务端会下发瓜分结束时间awardEndTime,服务端当前时间timeStamp,前端需要计算出来时间差,并展示在页面中。

二、失败案例

在页面初始化的时候拿到awardEndTime和timeStamp,两者的差值得到倒计时所剩时间,用setInterval进行倒计时。

useEffect(() => {
    let endCountDown = awardEndTime - timeStamp
    countDown( Math.floor(endCountDown/1000))
  }, [])
  
const CountDown = (maxtime) => {
    timer = setInterval(() => {
      if (maxtime > 0) {
        --maxtime
        let min = Math.floor(maxtime/60)
        let sec = Math.floor(maxtime%60)
        ...
          } else {
            clearInterval(timer);
          }
      }, 1000)
}

自测阶段,在一部手机上没有发现倒计时有问题,两部手机一起测试的时候发现问题了,其中一部手机显示倒计时还剩2分钟,而另一部手机显示倒计时还有5分钟,明显出bug了。查找bug的时候发现,将倒计时页面退到后台,此时倒计时就不再执行了,导致重新回到页面的倒计时是从退出的时刻计时开始计算的。

三、问题解决

直接上代码

useEffect(() => {
    let timeGap = timeStamp > 0 ? new Date().getTime() - timeStamp : 0;
    CountDownNew(awardEndTime, timeGap)
}, [])

const CountDownNew = (endTime, timeGap) => {
    timer = setInterval(() => {
        let startTime = new Date().getTime() - timeGap;
        let maxtime = Math.floor((endTime - startTime) / 1000);
        if (maxtime > 0) {
            --maxtime
        let min = Math.floor(maxtime/60)
        let sec = Math.floor(maxtime%60)
        ...
        } else {
            clearInterval(timer);
        }
    }, 1000)
}

问题轻松解决~

四、总结

1、失败原因

页面首次加载的时候,从接口拿到了首次加载的服务端时间和倒计时结束时间,并对时间差倒计时,当手机退到后台,再从后台回来时,不会重新请求接口去拿最新的服务端的当前时间,还是用过期的服务端时间,倒计时肯定不准确了。

2、优化思路

整体思路是每次倒计时都对当前时间做校准,得到最新的时间差。因为拿不到服务端的当前时间,所以要用客户端的时间表示服务端时间。每部手机的客户端时间展示可能会不同,但是他们和服务端时间的差值是固定的,在初始化的时候拿到两者的差值timeStamp,后面倒计时的时候用客户端的时间去校准服务端的时间就可以了。