更新:
我只是运行了一个简单的脚本,该脚本以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作业。但是我不明白为什么这会导致问题。
答案 0 :(得分:1)
如果没有所有源代码,很难知道发生了什么,我知道您无法提供它,但这对于讨论至关重要。
当您以延迟X ms的时间调用setTimeout
(或setInterval
)时-重要的是要知道这并不意味着回调将在X ms之后被调用。很难掌握,但这是事实。
来自MDN docs(大约是setTimeout
,但也适用于setInterval
):
零延迟实际上并不意味着回叫将在零毫秒后触发。给定时间间隔后,以0(零)毫秒的延迟调用setTimeout不会执行回调函数。
那么实际发生了什么?事件循环有一个任务队列(嗯,它可能有多个任务,但是为了简化讨论,让我们坚持一个)。当您致电setTimeout
/ setInterval
/承诺时,这些任务会加到任务队列中,如果一个任务花费很长时间(毫秒级),另一个可能会延迟。
我猜您的myOperations
包含的操作会扭曲其他任务的超时/间隔。
解决方案?就像您说的那样,cron听起来像是要走的路。每个operation
将在不同的过程中执行,因此,不同的事件循环将解决您的问题。
在更新后进行编辑
您看到的是js中的计时器不受信任,可能与您最初的问题无关,取决于myOperations
,这很难说。更多信息here和here