2013-10-20 40 views
2

我開始開發我的node.js應用程序的工作,但我不能「認爲異步」。 在我的函數中,我必須做一個查詢,對於每一行我都必須做另一個查詢來計算最終結果並創建我的json。 我嘗試這樣做:Node.js:forEach內部async.series

async.series([ 
    function(callback) { 
      db.myCannedResponseList(req.params.websiteid, function(err,questions) { 
       if (err) return callback(err); 
       ... 
       callback(); 
      }); 
     }, 
    function(callback) { 
      async.forEachSeries(temp,function(quest,callback) { 
        db.getCannedAnswer(quest.id, function(err,answers) { 
         console.log(answers); 
        }); 
      }, function(err) { 
       if (err) return next(err); 
      }); 
      callback(); 
     } 
    ], 
     function(err) { 
      if (err) return next(err); 
      res.json(output); 
    }); 

但有一個問題:後res.json(輸出)getCannedAnswer的結果顯示。 我該如何解決它?

回答

5

forEachSeries完成時,您需要調用回調。您還需要調用傳遞給forEachSeries處理函數的回調:

async.forEachSeries(temp, function(quest, callback2) { 
    db.getCannedAnswer(quest.id, function(err, answers) { 
    console.log(answers); 
    // call the callback for forEachSeries so it can proceed: 
    callback2(); 
    }); 
}, callback); // forEachSeries is done here, call the callback for async.series 
+2

也許只能通過'callback'來代替匿名函數(err)'。它會拋出''next next(err);'因爲'next'在那裏不存在(除非它在給定片段之外定義)。 –

+0

@JonathanLonowski很對,我會更新我的答案:) – robertklep

0

你的異步函數的嵌套,因此需要是你的回調。

這裏有一個辦法:

async.series([ 
     //async.apply(db.myCannedResponseList,req.params.websiteid), // This is equivalent to the first function below 
     //db.myCannedResponseList(req.params.websiteid,callback), // This is equivalent too 
     function(callback) { 
      db.myCannedResponseList(req.params.websiteid, callback); 
     },  
     function(callback) { 
      // I'm not sure forEach is the best choice here 
      // since it's callback isn't called with all the results so it won't be able to be forwarded... 
      // Personally, I use async.times for something like this. 
      async.times(temp.length,function(i,next) { 
       db.getCannedAnswer(temp[i].id,next); 
      },callback) 
     } 
    ],function(err) { 
      if (err) return next(err); 
      res.json(output); 
    }); 

我不知道這是什麼功能應該做的,但如果你在async.series遇到錯誤,你應該調用res.json(500,error)或成功不叫res

一個好方法是將這個函數完全分開,並在完成時調用另一個回調函數。那麼你會在那裏撥打res

另外,不是將數組傳遞給async.series,而是傳遞一個對象,以便命名空間。

完整的示例:

function getCannedStuff(data,callback){ 
     async.series({ 
      list : async.apply(db.myCannedResponseList,data.websiteid), 
      answer : function(cb) { 
       async.times(data.temp.length,function(i,next) { 
       db.getCannedAnswer(data.temp[i].id,next); 
       },cb) 
      } 
     },callback); 
    } 

然後從另一模塊調用該函數:

getCannedStuff({ 
     websiteid: req.params.websiteid, 
     temp:temp 
    },function(error,results) { 
     console.log(results.list); 
     console.log(results.answer); 
     if(err) return res.json(500,{error : error}); 
     res.json(results) 
    }); 

你應該決定是否要控制內部或外部getCannedStuff錯誤,但它是通過一種好方法他們一起,並沒有做所有的時間if(err),看看他們是否發生。

+0

在最終回調中出現錯誤時調用'next(err)'是Express應用程序的非常標準的行爲,該應用程序定義了一個應用程序範圍的錯誤處理程序。 – robertklep

+0

@robertklep真。試圖用這個例子來表達我的觀點 – Maroshii