可以随着时间的推移setInterval漂移吗?

时间:2013-08-10 22:46:49

标签: javascript node.js

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

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

millisTillNexthour = "Calculate millis remaining until next hour"

setTimeout(function() {
  setInterval(function() {
    cache.clear();
  }, 60000*15);
}, millisTillNexthour);

我的期望是,即使此过程一直运行,缓存也会在每天的每个小时每15分钟清除一次。

我的问题是:可以随着时间的推移setInterval漂移吗?

例如:现在它清除10:00 10:15 10:30 10:45 11:00 ......

处的缓存

是否会发生,而不是10:15系统时间,setInterval会在10:20系统时执行,因为它应该在10:15清除缓存?

我不确定这是如何运作的。请说清楚。我希望我能很好地解释我的问题。

6 个答案:

答案 0 :(得分:1)

setInterval肯定会漂移(虽然我同意不应该)。我正在运行一个间隔为30秒的Node.js服务器。在每个刻度线上,会产生一些异步Web请求,从头到尾大约需要1秒钟。在29秒内没有其他用户级/应用程序处理。

但是,我从服务器日志中注意到,在30分钟的过程中,发生了100ms的漂移。当然,底层操作系统不应该归咎于漂移,它只能是Node.js设计或实现的一些缺陷。

答案 1 :(得分:1)

我很失望地注意到setInterval的NodeJS实现中存在一个错误。请看这里:

https://github.com/nodejs/node/issues/7346#issuecomment-300432730

答案 2 :(得分:0)

您可以使用Date()对象设置特定时间,然后在日期中添加一定的毫秒数。

答案 3 :(得分:0)

肯定可以因为Javascript的工作方式(See Event Loop

当其他排队事件完成时,Javascript事件循环执行setInterval队列。这些事件需要一些时间,它会影响你的setInterval函数的执行时间,并且随着时间的推移最终会逐渐消失。

答案 4 :(得分:0)

我在这里参加聚会的时间可能要晚一些,但这就是我现在通过递归调用setTimeout()函数而不是setInterval()解决这个特殊的时间滑移问题的方法。

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

在每次迭代中,该函数都会相对于先前计算的预期时间检查 actual 执行时间,然后从“ interval”中减去差值以产生“ adjustedInterval”。这种差异可能是正的也可能是负的,结果表明,实际执行时间倾向于在“真实”值+/-〜5ms左右波动。

无论哪种方式,如果您有一个每分钟执行一次的任务,并且将其运行一整天,那么使用此功能,您可以期望-在整天中,每个小时将有60次迭代发生。您不会有一个偶然的小时,只能得到59个结果,因为最终整整一分钟都消失了。

答案 5 :(得分:-1)

setInterval不应该漂移在一个完美的世界里。由于其他事情占用系统资源,它可能会延迟。如果您需要更精确的解决方案,请使用clock()函数"校准"你的节点。