2014-03-06 61 views
0

我正在做一個for循環來查找來自mongodb的結果,並concat數組。但是當循環結束時,我沒有得到最終結果數組。我是node.js的新手,我認爲它不像Objective-C回調那樣工作。node.js嵌套回調,得到最終結果數組

app.get('/users/self/feed', function(req, res){ 
    var query = Bill.find({user: req.param('userId')}); 
    query.sort('-createdAt'); 
    query.exec(function(err, bill){ 
     if (bill) { 
      var arr = bill; 
      Following.findOne({user: req.param('userId')}, function(err, follow){ 
       if (follow) { 
        var follows = follow.following; //this is a array of user ids 
        for (var i = 0; i < follows.length; i++) { 
         var followId = follows[i]; 
         Bill.find({user: followId}, function(err, result){ 
          arr = arr.concat(result); 
          // res.send(200, arr);// this is working. 
         }); 
        } 
       } else { 
        res.send(400, err); 
       } 
      }); 
      res.send(200, arr); //if put here, i am not getting the final results 
     } else { 
      res.send(400, err); 
     } 
    }) 
}); 

回答

1

雖然我不完全熟悉的MongoDB,他們documentation的快速閱讀表明,他們提供了一個異步 Node.js的接口。

這就是說,無論是findOnefind操作開始,但不要被你達到res.send(200, arr)意味着arr仍然是空的時候一定完整。

相反,你應該把你的反應回來一次所有異步調用完成這意味着你可以這樣做:

var billsToFind = follows.length; 
for (var i = 0; i < follows.length; i++) { 
    var followId = follows[i]; 
    Bill.find({user: followId}, function(err, result){ 
     arr = arr.concat(result); 
     billsToFind -= 1; 
     if(billsToFind === 0){ 
     res.send(200, arr); 
     } 
    }); 
} 

該方法使用了所有的內部異步調用的計數器(I」因爲我們目前正在其回調內部),因此忽略了findOne。當每個Bill.find調用完成時,遞減計數器,一旦它達到0,這意味着所有的回調已經觸發(這是因爲Bill.find被調用,數組follows中的每個項目都有效),並且它會發迴帶有完整數組的響應。

0

的確如此。您在for內的代碼將同時並行執行(並且我認爲具有相同的值i)。如果您在for循環內部和之後添加了console.log,您會發現外部文件會在打印之前被打印。

你可以用你的for到的功能,並通過內部採用並聯或串聯async模塊(https://www.npmjs.org/package/async)執行它們的代碼,並從async.parallelasync.series的最後一個參數獲取最終結果。