Javascript 时间间隔会随时间漂移吗?
我有两个node.js Web服务器。我在Web服务器中缓存数据。我根据系统时间同步缓存加载/清除。我已经完成了所有主机的时间同步 现在,我使用以下代码每15分钟清除一次缓存:Javascript 时间间隔会随时间漂移吗?,javascript,node.js,Javascript,Node.js,我有两个node.js Web服务器。我在Web服务器中缓存数据。我根据系统时间同步缓存加载/清除。我已经完成了所有主机的时间同步 现在,我使用以下代码每15分钟清除一次缓存: millisTillNexthour = "Calculate millis remaining until next hour" setTimeout(function() { setInterval(function() { cache.clear(); }, 60000*15); }, milli
millisTillNexthour = "Calculate millis remaining until next hour"
setTimeout(function() {
setInterval(function() {
cache.clear();
}, 60000*15);
}, millisTillNexthour);
我的期望是,即使这个过程永远运行,缓存也会在一天中每15分钟被清除一次
我的问题是:时间间隔会随时间漂移吗
例如:现在它在10:00 10:15 10:30 10:45 11:00…
是否会发生这样的情况,即setInterval不是在10:15系统时间执行,而是在10:20系统时间执行,而应该在10:15清除缓存
我不知道这是怎么回事。请给我点光。我希望我能很好地解释我的问题。设置间隔不应该在完美世界中漂移。它可能会因为其他事情占用系统资源而延迟。如果您需要更精确的解决方案,请使用clock()函数“校准”节点。您可以使用Date()对象设置特定时间,然后在日期上添加一定数量的毫秒
setInterval
肯定在漂移(尽管我同意不应该如此)。我正在以30秒的间隔运行Node.js服务器。在每个刻度上,都会发出一些异步web请求,从开始到结束大约需要1秒。在此29秒内,没有其他用户级/应用程序处理发生
但是,我从服务器日志中注意到,在30分钟的过程中,出现了100毫秒的漂移。当然,底层操作系统并不是造成这种漂移的原因,它只能是Node.js设计或实现的一些缺陷。我非常失望地注意到setInterval的NodeJS实现中存在一个bug。请看这里:
由于Javascript的工作方式,它肯定可以
Javascript事件循环在其他排队事件完成时执行setInterval队列。这些事件将花费一些时间,它将影响setInterval函数的执行时间,并且随着时间的推移,它最终会逐渐消失。我可能会晚到一点才参加这里的聚会,但这就是我刚才使用递归调用的setTimeout()解决这个特定时间滑动问题的方法函数而不是使用setInterval() 在每次迭代中,该函数将检查实际执行时间与之前计算的预期时间,然后从“interval”中扣除差异以生成“adjustedInterval”。这种差异可能是正的,也可能是负的,结果表明实际执行时间往往在“真”值+/-~5ms左右波动
无论哪种方式,如果你有一个每分钟执行一次的任务,并且你运行了一整天,使用这个函数,你可以预期——在一整天中——每一个小时将有60次迭代发生。你不会偶尔有一个小时只得到59个结果,因为最后整整一分钟都过去了。除非有其他东西阻止了它的执行,否则它应该尽可能接近
:15执行,否。setInterval
是专门为解决使用setTimeout
调用自身(并会漂移)而设计的。然而,伊恩是对的;如果某个程序在运行回调时将其阻塞5分钟,则在该阻塞解除之前,该程序不会运行。在金融交易或核威慑方面不要依赖于此。我发现了另一个类似的帖子:这不会提供比他们已经拥有的更强大的功能。除非它基于一个对象或数组,包含24小时内每15分钟一次的表示,并且缓存在事件中被清除。不过,只是在这里大声思考。。。。基于这样一种想法,即某些东西确实可能会占用系统资源,但计算机时钟会一直滴答作响。在内部,setInterval
使用系统时钟。要明确的是,setInterval
永远不会漂移,但它可能必须在触发之前等待(如果在它应该运行时有什么东西阻塞了它)。这适用于您可能做的所有事情,除了接管内核任务和热等待之外,尽管在线程更普遍的其他语言中,这不是一个问题(导致阻塞的事情更少)。好的。你说得对。在这种情况下–如果该函数在web worker上运行会怎么样?那会有帮助吗?
var interval = 5000;
var adjustedInterval = interval;
var expectedCycleTime = 0;
function runAtInterval(){
// get timestamp at very start of function call
var now = Date.now();
// log with time to show interval
console.log(new Date().toISOString().replace(/T/, ' ').replace(/Z/, '') + " runAtInterval()");
// set next expectedCycleTime and adjustedInterval
if (expectedCycleTime == 0){
expectedCycleTime = now + interval;
}
else {
adjustedInterval = interval - (now - expectedCycleTime);
expectedCycleTime += interval;
}
// function calls itself after delay of adjustedInterval
setTimeout(function () {
runAtInterval();
}, adjustedInterval);
}