2015-11-23 38 views
0

我在async.eachSeries上遇到困難。我創造了一個代碼的和平來說明。async.eachSeries無法正常工作

const arr = [1, 2, 3, 4, 5, 6, 7]; 
function doJob(callback){ 
    debugger; //#1 
    async.eachSeries(arr, function(task, cb){ 
     console.log('Starting checking function'); 
     debugger; //#2 
     if(task%2 === 0){ 
      debugger; //#3 
      console.log('Task even: ' + task); 

      r.exists("somekty", function(err ,result){ 
       if(err || result){ 
        debugger; //#4 
        cb(null); 
       }else{ 
        debugger; //#5 
        cb(null); 
       } 
      }); 
     }else{ 
      debugger;//#6 
      console.log('Task odd: ' + task); 
       cb(null); 
     } 
     debugger;//#7 
    }, function(err){ 
     callback() 
    }); 
} 

setTimeout(function(){ 
    doJob(function(){ 
     console.log('All done!'); 
    }) 
}, 1000) 

當我執行上面的代碼中,預期的結果768,16爲(我): 命中:#1

1次迭代:#2 - #6

2迭代:#2 - #3 - #7 - #4#|| 5

3次迭代:.... ...

,繼續向前....但會發生什麼當它被首次裏面具有異步函數(redis)的「if」只是進入#7,並且從不停止在#4或#5並結束代碼。爲什麼?

我使用鐵節點進行調試。

回答

0

,但發生的事情是當它首次 的「如果」,有一個異步函數(Redis的)裏面,它只是去#7 ,從來沒有在#4#5停止並完成碼。爲什麼?

這就是異步代碼的工作原理。如果r.exists()是異步的,那麼調用它將啓動操作,然後代碼的其餘部分繼續執行。異步操作在完成之前不會阻塞。調用它們只是開始操作,然後代碼的其餘部分繼續執行。

所以,當task%2 === 0,那麼你會進入你的代碼分支。然後它會撥打r.exists(...)。這將啓動異步操作,然後您的代碼行將繼續運行。

在您的代碼中執行的下一件事是debugger;//#7,以便觸發。

此時async.eachSeries()將發揮作用,直到有人打電話cb(null),這在你的代碼時r.exists()完成,並調用其回調會發生,將不執行你的循環的下一次迭代。

task%2 === 0,你應該看到這個序列:

#2, #3, #7, #4|#5 

這顯然是你觀察到的東西。


僅供參考,它有時會造成混淆使用了大量調試斷點時,因爲停在斷點本身影響各種操作的時機來理解你的代碼的真實時(它給本地代碼異步操作的機會坐在斷點處運行並完成)。在理解異步操作的純時序時,通常使用console.log()語句輸出足夠的信息來記錄事情的真實順序通常會更好。

+0

是的,我同意你所說的一切,也理解。問題是,我希望它在意甲,這不是什麼情況。當腳本第一次進入「r.exists」時,它會進入#7(如預期的那樣),並應等到「r.exists」結束後再激活調試器#4或#5。但是會發生什麼呢,就是在命中#7後,代碼神奇地結束了,而沒有停在#4或#5。 –

+0

謝謝,我不知道這個異步調試「問題」。 –

+0

@HaroldFinch - 'async.eachSeries()'本身是異步的。所以調用它,只是啓動操作。一旦循環的第一次迭代完成並且該迭代正在等待異步操作,它之後的代碼行就會執行。這是Javascript中的異步編程。如果你想在'async.eachSeries()'操作完成後執行一些代碼,那麼你把這段代碼放在'async.eachSeries()'的最後一個回調中。這就是回調的目的。 – jfriend00