2015-06-14 75 views
3

我與+的NodeJS貓鼬工作,我試圖填充對象的數組,然後將其發送給客戶端後,但我不能做到這一點,反應總是空因爲它是在每個結束之前發送的。需要發送響應的forEach做

router.get('/', isAuthenticated, function(req, res) { 
Order.find({ seller: req.session.passport.user }, function(err, orders) { 
    //handle error 
     var response = []; 
     orders.forEach(function(doc) { 
     doc.populate('customer', function(err, order) { 
      //handle error 
      response.push(order); 
     }); 
     }); 
     res.json(response); 
    }); 
}); 

循環結束後有什麼辦法發送它嗎?

回答

5

基本上,你可以使用異步控制流管理的任何解決方案一樣async或承諾(見laggingreflex's answer瞭解詳細信息),但我會建議你使用專門的貓鼬的方法來填充整個數組在一個MongoDB查詢中。

最直接的解決方案是使用Query#populate method獲得已填充文件:

Order.find({ 
    seller: req.session.passport.user 
}).populate('customer').exec(function(err, orders) { 
    //handle error 
    res.json(orders); 
}); 

但是,如果由於某種原因,你不能使用這種方法,你可以調用Model.populate method自己來填充數組已經取得的文檔:

Order.populate(orders, [{ 
    path: 'customer' 
}], function(err, populated) { 
    // ... 
}); 
+0

就是這樣。 「查詢#填充」就像魅力一樣。非常感謝! – alexhzr

3

一種解決方案是使用的承諾。

var Promise = require('bluebird'); 

Promise.promisifyAll(Order); 

router.get('/', isAuthenticated, function(req, res) { 
    Order.findAsync({ seller: req.session.passport.user }) 
    .then(function(orders) { 
     return Promise.all(orders.map(function(doc){ 
      return Promise.promisify(doc.populate).bind(doc)('customer'); 
     })); 
    }).then(function(orders){ 
     // You might also wanna convert them to JSON 
     orders = orders.map(function(doc){ return doc.toJSON() }); 
     res.json(orders); 
    }).catch(function(err){ 
     //handle error 
    }); 
}); 

BlueBird.promisifyAll創建…Async版本的對象,這樣可以節省在配置初始承諾的額外步驟的所有功能。因此,而不是Order.find我在上面的例子中使用Order.findAsync

+0

我不知道承諾,因爲我是一個NodeJS總noob。我會研究他們和藍鳥。非常感謝你! – alexhzr