我遇到需要从nodejs(expressjs)代码触发mongodb查询的情况,并将查询结果作为对我的web api请求的响应传递,但在我的查询执行之前,下一行代码获取执行并发回空白响应。我写的代码如下,
router.get('/recent', function (req, res){
var result = [];
router.db.collection('Posts').find({},{ _id : 1, uid : 1, imagePath : 1, cntLikes : 1, uploadDate : 1}).limit(5).sort({ uploadDate : -1 }).toArray(function(err, docs) {
docs.forEach( function (doc){
router.db.collection('Users').findOne({ "_id" : mongodb.ObjectId(doc.uid)}, function (err, user){
doc.username = user;
result.push(doc);
});
});
res.send(result); // this line send empty result to caller
});
});
我已经尝试了回调方法,async.waterfall并以编程方式停止执行,但一切都失败了。我也尝试过承诺,但我不认为承诺可以帮助我在这种情况下。
答案 0 :(得分:1)
您正在循环中使用另一个异步调用,该调用正在res.send(result)
之后执行。我认为你所追求的是async.map,所以也许在你的帖子回调中有类似的内容
function addUserToPost(item, callback) {
router.db.collection('Users').findOne({ "_id" : mongodb.ObjectId(doc.uid)}, function (err, user){
doc.username = user;
callback(err, doc);
});
}
async.map(docs, addUserToPost, function(err, posts) {
res.send(posts);
});
您希望将“帖子”映射到添加了用户信息的帖子。
答案 1 :(得分:1)
尝试这个:
router.get('/recent', function (req, res){
var result = [];
router.db.collection('Posts').find({},{ _id : 1, uid : 1, imagePath : 1, cntLikes : 1, uploadDate : 1}).limit(5).sort({ uploadDate : -1 }).toArray(function(err, docs) {
var counter = 0;
docs.forEach( function (doc, index){
counter++;
router.db.collection('Users').findOne({ "_id" : mongodb.ObjectId(doc.uid)}, function (err, user){
doc.username = user;
result.push(doc);
if(counter === index){
res.send(result);
}
});
});
});
});