Javascript 时间间隔会随时间漂移吗?

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

我有两个node.js Web服务器。我在Web服务器中缓存数据。我根据系统时间同步缓存加载/清除。我已经完成了所有主机的时间同步

现在,我使用以下代码每15分钟清除一次缓存:

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);
}