精确的时间
开的坑太多了,有时候自己都忘了,现在想吐槽点什么,都不知道放在哪个帖子里好,坑王实锤。
一个问题
前端显示时间,很基础的操作,基本学到 JS 就可以做了。一般就是设置一个定时器(setInterval
),看英文其实是设置一个“间隔”,实际效果是间隔指定的时间执行对应的操作。所以间隔一秒,更新一下时间,我们就能看到页面中时间的般变化了。
道理上没问题,但是如果第一次我们在 1 秒 95 的时候获取时间,读取的秒数字是 1,显示出来,但这时候基本已经到 2 秒了,可是下次更新在一秒以后,就是 2 秒 95,于是这个显示就始终偏差接近一秒。偏差不大,一般没啥影响,所以大家也都不这么着了。
当然,如果看着这个时间抢秒杀就有点不靠谱,何况这个偏移程度还不固定。不过我们也要了解,这就是个电脑本地时间,即便现在有网络对时,也不是绝对精确,所以种种偏差叠加,这点细节真的不那么重要。
但有的网页时间不显示秒,于是有人想当然的把更新间隔设置为了一分钟,这就过了,同理上面,最多可能偏差接近一分钟。
第一种方法
怎么解决呢?收缩更新间隔,比如依然一秒更新一次,就比较准确了。
继续同理,那显示秒钟的呢,也收缩更新间隔,1 毫秒更新一次,准确了——并不是!JS 做不了那么小间隔的操作,会自己对齐到一个它所能执行的最小时间间隔,比如 15 毫秒一次。
但无论如何,这个问题算是解决了吧。可是频率过高的更新是不是有点浪费系统性能呢,单纯靠暴力换精度,就不太优雅。
第二种方法
在学习 setInterval
的同时,一定也都学习了 setTimeout
。这就是一个一次性的定时器。
那么获取当前时间,看一下距离下一次更新的毫秒数(相对精确),设定一个计时器(setTimeout
)用来触发下一次更新,如此循环往复……
精度提高,性能也差不太多,至少比高频好太多了。然后可能就遇到回调过深的问题了……
第三种方法
要不结合一下,用 setTimeout
调整第一次的偏移,让时间对齐,然后后面就用 setInterval
好了。
第一次只要对齐了,后面间隔一样,就应该都对齐了。这挺合理的。但是现在浏览器为了节省性能,可能对后台标签进行一定程度的暂停。会不会再次导致打乱……
第四种方法
还是 setInterval
,间隔一秒执行一次,但是并不是直接更新时间,而是计算一下距离下一秒还有多少毫秒,设定一个定时器(setTimeout
)在那个时间更新。
这样每次都调整一下偏差,比最初的方法性能消耗大概翻倍,但用在精确度为秒(或者更大)的场景下比较合理。能够在各种场景下保证相对精确,且性能消耗也不算过分。
但是有点小问题,如果因为程序的原因导致某些延迟,那么可能导致更新推迟,于是产生跳秒现象,解决办法是稍微收缩更新间隔,比如 900 毫秒更新一次。
其实有其他方法,但是大佬们的玩法我真看不懂,就用最基础的东西初步解决一下。精度上,第四种方法的偏差控制在大约 10 ms,日常可以接受了。