2014-08-28 76 views
2

在Node.js中執行一系列異步操作的好方法是什麼?這適用於腳本類型的應用程序,應用程序應該從命令行運行,然後完成作業,它不在應該坐在後臺並同時處理幾個不同事物的服務器上下文中。在node.js中執行一系列異步操作

我知道承諾/ A +又名Thenables的,但語法沒有得到那該多好:

do_some_stuff().then(
    function() { 
     do_some_other_stuff().then(
      function() { 
       do_the_last_stuff().then(
        function() { 
         // we are done with everything! 
        } 
       ) 
      } 
     ) 
    } 
); 

當我們有更多的操作壓痕將使它看起來很醜陋。

我喜歡茉莉花是如何做到的,異步操作在這裏傳遞了一個函數,它在完成時應該調用它。基於這個想法,我創建了一個名爲AsyncSequence的東西。 AsyncSequence執行一系列操作,每個操作都會通過一個done函數,該函數應在完成時調用。使用AsyncSequence上面看起來像:

AsyncSequence.run(
    function(done) { 
     do_some_stuff().then(done); 
    }, 
    function(done) { 
     do_some_other_stuff().then(done); 
    }, 
    function(done) { 
     do_the_last_stuff().then(done); 
    }, 
    function() { 
     // we are done with everything! 
    } 
); 

這個工作,它看起來更好,我認爲,但我不知道是否有這樣做的更「標準」的方式?當你調整Node.js程序員看到這個的時候,有沒有什麼類似於我的AsyncSequence?或者不完全相似的東西,但可以用於相同的目的?

+1

你寫什麼,似乎類似於https://github.com/caolan/async – 2014-08-28 09:05:42

回答

3

輕諾/ A +,then可以鏈接,使您的第一個例子:

do_some_stuff() 
.then(do_some_other_stuff) 
.then(do_the_last_stuff) 
.then(function() { 
    // we are done with everything! 
}); 

看着承諾爲你將不得不在未來值的容器,then變換未來值插入到另一價值(有點像[].map)。但是,如果您傳遞給then的函數返回另一個承諾,它將被解包。舉一個更具體的例子:

getPostData(req).then(function(data) { 
    return createNewUser(data); 
}).then(function(user) { 
    return JSON.stringify(user); 
}).then(function(json) { 
    return successResponse(json); 
}).then(function(body) { 
    res.end(body); 
}); 

這個例子使用顯式函數參數使流動更加明顯。 createNewUser返回一個表示將用戶對象保存到數據庫的承諾,而JSON.stringify當然只是返回一個字符串。 Promises/A +可以處理和鏈接兩種返回值。

+0

但是如果操作本身是異步的?假設createNewUser必須調用外部服務,那麼它將如何工作? – 2014-08-28 09:30:16

+0

@MikaelLindqvist這是Promises的全部要點,與「異步」功能一起使用。下一個'.then'將一直等到用戶被創建。 – rollingBalls 2014-08-28 09:41:10

+0

創建新用戶還應該返回一個承諾。這反過來可以被鏈接 – Max 2014-08-28 09:44:24

1

使用異步模塊。請參閱watefall方法。 https://github.com/caolan/async

async.waterfall([ 
    function(callback){ 
     callback(null, 'one', 'two'); 
    }, 
    function(arg1, arg2, callback){ 
     // arg1 now equals 'one' and arg2  now equals 'two' 
     callback(null, 'three'); 
    }, 
    function(arg1, callback){ 
     // arg1 now equals 'three' 
     callback(null, 'done'); 
    } 
], function (err, result) { 
    // result now equals 'done'  
}); 
+0

是的,這是非常相似的,但不幸的是,回調不符合承諾。我不能這樣做:async.waterfall([function(cb){some_op.then(cb)}]);因爲回調期望成爲第一個參數爲空。 – 2014-08-28 09:27:18

+0

如果你想堅持承諾,你應該使用承諾鏈像馬特sugguested。由於節點生態系統是圍繞回調建立的,因此您應該確定使用承諾。 – Max 2014-08-28 09:40:24