2014-06-10 39 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;