js前端如何写一个精确的倒计时代码
关于写倒计时大家可能都都比较熟悉,使用setTimeout或setInterval就可以搞定。几秒钟或者几分钟的倒计时这样写没有问题,但是如果是长时间的倒计时,这样写就会不准确。如果用户修改了他的设备时间,这样的倒计时就没有意义了。今天就说说写一个精确的倒计时的方法。
原理
众所周知setTimeout或者setInterval调用的时候会有微小的误差。有人做了一个demo来观察这个现象并对其做了修正。短时间的误差倒也可以接受,但是作为一个长时间的倒计时,误差累计就会导致倒计时不准确。
因此我们可以在获取剩余时间的时候,每次new一个设备时间,因为设备时间的流逝相对是准确的,并且如果设备打开了网络时间同步,也会解决这个问题。
但是,如果用户修改了设备时间,那么整个倒计时就没有意义了,用户只要将设备时间修改为倒计时的endTime就可以轻易看到倒计时结束是页面的变化。因此一开始获取服务端时间就是很重要的。
简单的说,一个简单的精确倒计时原理如下:
- 初始化时请求一次服务器时间serverTime,再new一个设备时间deviceTime
- deviceTime与serverTime的差作为时间偏移修正
- 每次递归时new一个系统时间,解决setTimeout不准确的问题
代码
获取剩余时间的代码如下:
/** *获取剩余时间 *@param{Number}endTime截止时间 *@param{Number}deviceTime设备时间 *@param{Number}serverTime服务端时间 *@return{Object}剩余时间对象 */ letgetRemainTime=(endTime,deviceTime,serverTime)=>{ lett=endTime-Date.parse(newDate())-serverTime+deviceTime letseconds=Math.floor((t/1000)%60) letminutes=Math.floor((t/1000/60)%60) lethours=Math.floor((t/(1000*60*60))%24) letdays=Math.floor(t/(1000*60*60*24)) return{ 'total':t, 'days':days, 'hours':hours, 'minutes':minutes, 'seconds':seconds } }
获取服务器时间可以使用mtop接口mtop.common.getTimestamp
然后可以通过下面的方式来使用:
//获取服务端时间(获取服务端时间代码略) getServerTime((serverTime)=>{ //设置定时器 letintervalTimer=setInterval(()=>{ //得到剩余时间 letremainTime=getRemainTime(endTime,deviceTime,serverTime) //倒计时到两个小时内 if(remainTime.total<=7200000&&remainTime.total>0){ //dosomething //倒计时结束 }elseif(remainTime.total<=0){ clearInterval(intervalTimer); //dosomething } },1000) })
这样的的写法也可以做到准确倒计时,同时也比较简洁。不需要隔段时间再去同步一次服务端时间。
补充
在写倒计时的时候遇到了一个坑这里记录一下。
千万别在倒计时结束的时候请求接口。会让服务端瞬间QPS峰值达到非常高。
如果在倒计时结束的时候要使用新的数据渲染页面,正确的做法是:
在倒计时结束前的一段时间里,先请求好数据,倒计时结束后,再渲染页面。
关于倒计时,如果你有什么更好的解决方案,欢迎评论交流。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。