这篇文章给大家分享的是有关js前端怎样写一个精确的倒计时代码的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
原理
众所周知 setTimeout 或者 setInterval 调用的时候会有微小的误差。有人做了一个 demo 来观察这个现象并对其做了修正。短时间的误差倒也可以接受,但是作为一个长时间的倒计时,误差累计就会导致倒计时不准确。
因此我们可以在获取剩余时间的时候,每次 new 一个设备时间,因为设备时间的流逝相对是准确的,并且如果设备打开了网络时间同步,也会解决这个问题。
但是,如果用户修改了设备时间,那么整个倒计时就没有意义了,用户只要将设备时间修改为倒计时的 endTime 就可以轻易看到倒计时结束是页面的变化。因此一开始获取服务端时间就是很重要的。
简单的说,一个简单的精确倒计时原理如下:
初始化时请求一次服务器时间 serverTime,再 new 一个设备时间 deviceTime
deviceTime 与 serverTime 的差作为时间偏移修正
每次递归时 new 一个系统时间,解决 setTimeout 不准确的问题
代码
获取剩余时间的代码如下:
/**
* 获取剩余时间
* @param {Number} endTime 截止时间
* @param {Number} deviceTime 设备时间
* @param {Number} serverTime 服务端时间
* @return {Object} 剩余时间对象
*/
let getRemainTime = (endTime, deviceTime, serverTime) => {
let t = endTime - Date.parse(new Date()) - serverTime + deviceTime
let seconds = Math.floor((t / 1000) % 60)
let minutes = Math.floor((t / 1000 / 60) % 60)
let hours = Math.floor((t / (1000 * 60 * 60)) % 24)
let days = Math.floor(t / (1000 * 60 * 60 * 24))
return {
'total': t,
'days': days,
'hours': hours,
'minutes': minutes,
'seconds': seconds
}
}
获取服务器时间可以使用 mtop 接口 mtop.common.getTimestamp
然后可以通过下面的方式来使用:
// 获取服务端时间(获取服务端时间代码略)
getServerTime((serverTime) => {
//设置定时器
let intervalTimer = setInterval(() => {
// 得到剩余时间
let remainTime = getRemainTime(endTime, deviceTime, serverTime)
// 倒计时到两个小时内
if (remainTime.total <= 7200000 && remainTime.total > 0) {
// do something
//倒计时结束
} else if (remainTime.total <= 0) {
clearInterval(intervalTimer);
// do something
}
}, 1000)
})
这样的的写法也可以做到准确倒计时,同时也比较简洁。不需要隔段时间再去同步一次服务端时间。
补充
在写倒计时的时候遇到了一个坑这里记录一下。
千万别在倒计时结束的时候请求接口。会让服务端瞬间 QPS 峰值达到非常高。
如果在倒计时结束的时候要使用新的数据渲染页面,正确的做法是:
在倒计时结束前的一段时间里,先请求好数据,倒计时结束后,再渲染页面。
感谢各位的阅读!关于“js前端怎样写一个精确的倒计时代码”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!