setInterval在一段时间内持续增加

时间:2018-06-22 11:26:55

标签: node.js setinterval v8 event-loop

更新
我只是运行了一个简单的脚本,该脚本以1s的间隔打印new Date()

setInterval(function(){
    console.log(new Date());
},1000)

大约5-6分钟后,它跳过了1秒。
看来这可能是因为setInterval是如何在内部工作的。

原始帖子:
请注意,我没有源代码可以模拟这一点,因为我的代码原始代码包含大量的网络和文件系统操作,我无法在此处放置。

我正在设置60秒的多个(500)setIntervals。 每个时间间隔是在彼此间隔大约50毫秒后设置的

for(let i=1;i<500;i++){
    delayStart(i)
}

function delayStart(index){
    setTimeout(start,index*50)
}

function start(){
    setInterval(myOperations,60*1000)
}

myOperations由一些TCP调用,同步文件读取和异步文件写入组成。 所有这些操作将在35秒内完成,此后脚本将处于空闲状态。由于未填充事件循环,因此我看不到间隔执行会被延迟的原因。

我的日志显示开始时间有所增加。
第一次执行是从第十秒开始的。

7分钟后:11秒
22分钟后:第12秒
57分钟后:15秒
71分钟后:19秒

71分钟内增加了9秒。
我知道这似乎并不多,但是我正在做的操作需要每分钟进行一次。

是的,我曾经考虑过使用数据库和cron作业。但是我不明白为什么这会导致问题。

1 个答案:

答案 0 :(得分:1)

如果没有所有源代码,很难知道发生了什么,我知道您无法提供它,但这对于讨论至关重要。

当您以延迟X ms的时间调用setTimeout(或setInterval)时-重要的是要知道这并不意味着回调将在X ms之后被调用。很难掌握,但这是事实。

来自MDN docs(大约是setTimeout,但也适用于setInterval):

  

零延迟实际上并不意味着回叫将在零毫秒后触发。给定时间间隔后,以0(零)毫秒的延迟调用setTimeout不会执行回调函数。

那么实际发生了什么?事件循环有一个任务队列(嗯,它可能有多个任务,但是为了简化讨论,让我们坚持一个)。当您致电setTimeout / setInterval /承诺时,这些任务会加到任务队列中,如果一个任务花费很长时间(毫秒级),另一个可能会延迟。

我猜您的myOperations包含的操作会扭曲其他任务的超时/间隔。

解决方案?就像您说的那样,cron听起来像是要走的路。每个operation将在不同的过程中执行,因此,不同的事件循环将解决您的问题。

在更新后进行编辑

您看到的是js中的计时器不受信任,可能与您最初的问题无关,取决于myOperations,这很难说。更多信息herehere