簡體   English   中英

所有節點“回調”功能都可能是異步的嗎?

[英]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.nextTicksetTimeoutsetInterval 要更實際地模擬異步調用,請執行以下操作:

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中。 到那時,您遇到了問題,因為foobar的調用順序將翻轉。

在我看來,只有兩種寫代碼的好方法,就像您做的那樣:要么將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM