2014-06-10 37 views
3

clearTimeout之前比方说,我这样做:的Javascript内部 - 它触发

var timer = setTimeout(function() { 
    console.log("will this happen?"); 
}, 5000); 

然后只需不到5秒后,(在的NodeJS例如从网络事件)触发另一个回调并清除它:

clearTimeout(timer); 

是否有可能从setTimeout调用回调已经在排队在这一点上要执行,如果这样将clearTimeout是及时制止呢?

为了说明问题,我正在讨论setTimeout时间实际到期并且解释器开始执行它的过程,但另一个回调正在运行以便将消息添加到队列的情况。这似乎是其中一种竞争条件类型的东西,很容易解释。

回答

5

Node.js在单个线程中执行。

因此,不会有任何竞争条件,并且您可以可靠地在触发之前取消超时。

又见a related discussion (in browsers).

我说的是一种情况:setTimeout的时间已经到期,并解释开始执行它

的过程,而不必看着Node.js的内部,我不要认为这是可能的。所有东西都是单线程的,所以当代码运行时,解释器不能“做任何事情”。

您的代码必须在触发超时之前返回控制权。如果你在代码中放入一个无限循环,整个系统就会挂起。这都是“合作多任务”。

2

即使Node是单线程,问题描述的竞争条件也是可能的。

它可能发生,因为定时器是由本地代码触发的(在lib_uv中)。 最重要的是,节点将具有相同超时值的定时器分组。因此,如果您在同一毫秒内安排具有相同超时的两个定时器,它们将立即添加到事件队列中。

但放心的节点在内部解决了这个问题。从节点0.12.0引用代码:

timer.js > clearTimeout

exports.clearTimeout = function(timer) { 
    if (timer && (timer[kOnTimeout] || timer._onTimeout)) { 
    timer[kOnTimeout] = timer._onTimeout = null; 
    // ... 
    } 
} 

在清除超时,节点内部移除参考回调函数。所以,即使在竞争条件发生时,它可以做任何伤害,因为这些定时器将被跳过:

listOnTimeout

if (!first._onTimeout) continue;