[英]Are All Node “callback” Functions Potentially Asynchronous?
我是進入系統的(相對)節點新手,並且社區中的所有熱情“只需編寫回調,所有內容都是異步的並且是事件驅動的,不用擔心!” 使我對單個程序中的控制流有些困惑(或更籠統地說,是在較大程序中處理單個請求期間的控制流)
如果我在節點下運行以下程序
var foo = function(){
console.log("Called Foo");
};
var bar = function(){
console.log("Called Bar");
};
var doTheThing = function(arg1, callback){
callback();
};
doTheThing(true, function() {
foo();
});
bar();
是否有任何機會, foo
會后執行bar
? 當我通過命令行在本地運行程序時,總是
Called Foo
Called Bar
但是我看到好主意的福音派人士發出了許多警告,包括不要假設您認為回調會被調用 ,我不清楚他們是否只是在警告我有關庫實現的詳細信息或節點。當您使用函數對象作為參數時,js會做一些奇怪的/特殊的事情。
不,沒有機會。 不適用於該代碼。
如果您正在編寫自己的函數,或者可以訪問代碼,則無需假設一切都是同步的,而是如果您無法訪問代碼或沒有權限,則可以。尚未閱讀,那么不行,您不能假設回調將是同步的。
但是,進行這樣的假設是不好的做法 ,原因有兩個,首先是僅僅因為它現在是同步的,就不意味着其他人,或者健忘的未來您以后不能更改它,其次,因為如果它們都是同步的,為什么您/他們是否首先使用回調? 回調的全部要點是允許異步調用的可能性。 使用回調,然后像使它們始終保持同步一樣工作,即使您知道這種情況,也會使您的代碼對其他任何人造成混亂。
您的示例代碼是100%同步,單線程,簡單的從上到下。 但這是因為您不執行任何I / O,沒有任何真正的異步調用,並且不使用process.nextTick
, setTimeout
或setInterval
。 要更實際地模擬異步調用,請執行以下操作:
function fakeAsync(name, callback) {
setTimeout(function () {
callback(null, name);
}, Math.random() * 5000);
}
function logIt(error, result) {
console.log(result);
}
fakeAsync('one', logIt);
fakeAsync('two', logIt);
fakeAsync('three', logIt);
運行幾次,有時會看到亂序的結果。
foo在bar之后執行是否有可能?
在您當前的代碼中,沒有。 盡管您的doTheThing
函數具有異步函數簽名(即,將回調作為最后一個參數,對不知道該函數實現的局外人來說,這表明它是異步的),但它實際上是完全同步的,並且將在不產生callback
情況下調用callback
到運行時。
然而
您確實沒有理由為您的doTheThing
代碼提供一個異步簽名, 除非您doTheThing
在某個時候將真正的異步行為引入doTheThing
中。 到那時,您遇到了問題,因為foo
和bar
的調用順序將翻轉。
在我看來,只有兩種寫代碼的好方法,就像您做的那樣:要么將doTheThing
設置為同步(最重要的是:它將不依賴於I / O),這意味着您可以只需從函數返回:
doTheThing = function(arg1){
return null
};
doTheThing()
foo()
bar()
或直接更改doTheThing
的存根實現以包含對setImmediate
的調用,即
var doTheThing = function(arg1, callback){
setImmediate(function() { callback(); );
};
請注意,這也可以寫成
var doTheThing = function(arg1, callback){
setImmediate(callback);
};
但這僅僅是因為此時,回調不接受任何參數。 第一個版本更接近於您所擁有的版本。
一旦執行此操作, bar
將始終在foo
之前被調用,現在已經可以安全地在doTheThing
引入異步功能了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.