我的假设是时间总是向前发展,但显然有时它不会以这种方式发生。
我有以下示例:
var LOOP_MS = 100;
var prevCall = +new Date();
setTimeout(function loop() {
foobar();
setTimeout(loop, LOOP_MS);
}, LOOP_MS);
function foobar() {
var now = +new Date(),
diff = now - prevCall; // expected to be somewhere around LOOP_MS
// do stuff
console.log(diff);
prevCall = now;
}
现在,大部分时间它按预期工作,diff
显示接近100的数字。当然,在现实生活中我希望数字会增加,特别是当用户的电脑正在进行一些繁重的操作。
我没想到的是,看到一个负数,但它发生了。怎么可能?我错过了什么吗?我想也许它可能是由不同的时区造成的,但事实并非如此。我也在不同的浏览器(Chrome,Firefox,Safari)中看到它,并且diff值非常不一致:从-9到-100 000。
大约有0.025%的情况发生在生产中,所以这不是一个大问题,但我想知道它究竟是如何发生的(即使在理论上)?
我认为通过在慢速VM中运行脚本并模拟高CPU负载,我设法在本地重现了几次,但我仍然不明白为什么函数会显示负数(意思是{{1 }}早于now
)。
答案 0 :(得分:3)
大多数计算机都配置为使用NTP服务器来设置系统时钟。
当系统时钟第一次正常设置时,它将保持同步而无需更新。
由于各种原因,有时(很少)系统时钟可能会不同步。
由于系统时钟与NTP服务器时间不匹配,因此它会更新并可能会倒退。
NTP服务(通常)配置为避免时钟倒退:如果"间隙"很小,NTP守护程序试图改为"减速"系统时钟直到它在sysnc中再次出现。但正如刚才所说,这取决于配置和时间间隔的大小。
我认为上述所有情况都会在极少数情况下导致您看到的问题。
你可能会觉得这很有趣:Is there a way to ensure ntp synced clock never moves backwards?
如果您使用的是macOS,可以尝试打开控制台并搜索ntpd
。
在我的机器上(MBP 10.9.5)我看到这样的几行......
Apr 2 01:11:40 mac-di-paolo.local ntpd[46]: ntpd: wake time set -1.848017 s
...记录系统时钟调整。
答案 1 :(得分:1)
prevCall
是一个带有通用名称的全局变量 - 是否可能有其他函数写入它?
答案 2 :(得分:0)
第一。您有一个不准确的等式,即使在高度准确的IE定时器中,至少会在延迟引用上给出-1到+1。这是正常的。
第二。定时器具有低优先级执行,即使最轻微的客户端鼠标页面交互也可能会将其间隔时间缩短几毫秒。
所有其他同步操作,功能和事件将使它们(定时器)停止并导致给定间隔的更大量的干扰。
答案 3 :(得分:0)
实际上,通过更改计算机上的时间来实现这一目标非常容易。
一般来说很难解决这个问题,但你可能会发现一些更具特色的问题。例如,如果您在网站上显示倒计时时钟,那么您的服务器可以说出GMT的开始时间是什么,它的想法是什么"现在"是和剩下多少秒。每当出现问题" *时,您可以向服务器询问相同的信息,并且根据该信息,您可以将其与机器上的当地时间进行比较。基本上,您可以将服务器时间用作参考点而不是前端的时间。
出错 * - 我的意思是,计时器变为负数或自上次执行以来已经过了太多时间。太多时间可能意味着20秒。