如何在asynchronous调用期间填充数组并将其发送到响应对象中

这是我试图做的一个例子,检索mongo数据库中的所有post,为每个post填充作者,然后使用作者对象从Cloudinary检索configuration文件图片。

什么是正确的方式去做这个? 我已经尝试了许多方法来填充数组,并在响应中发送这些数据,但是由于asynchronous调用,它们在发送数据之前从不运行。

router.get('/posts',auth, function(req, res, next) { //var id = req.payload._id; Post.find(function(err, posts){ if(err){ return next(err); } posts.forEach(function(post){ post.populate('author',function(err,post){ post.image = cloudinary.image("v"+post.author.avatarVersion+"/profile/"+post.author._id,{ width:100, height:100,crop:'thumb',gravity:'face',radius:'max' }) //here the post object is updated console.log(post) }) }) //res.json(some posts array); }); }); 

感谢Dan Moldovan的解决scheme!

 router.get('/posts',auth, function(req, res, next) { var id = req.payload._id; Post.find({}).populate('author').exec(function(err,posts){ if(err){ return next(err); } var updatedPosts = []; posts.forEach(function(post){ post.image = cloudinary.image("v"+post.author.avatarVersion+"/profile/"+post.author._id,{ width:100, height:100,crop:'thumb',gravity:'face',radius:'max' }) updatedPosts.push(post); }) res.json(updatedPosts); }) 

你可以链接populate查询到第一个,并有一个最后的callback,如

 Post.find({}).populate('author').exec(function (err, posts) { if(err){ return next(err); } posts.forEach(function(post){ // here each post will already have author appended }); }); 

丹的解决scheme是正确的,但我想解释你遇到的问题。 因为post.populate()是一个数据库调用,这意味着代码是asynchronous的。 这意味着forEach()的下一篇文章将在.populate()完成前.populate()之前开始运行。 这意味着并不是所有的post都会在res.json()执行之前完成。 解决scheme(在这种情况下不需要,但可以由当前代码使用)是使用asynchronous库 :

 var async = require("async"); router.get('/posts',auth, function(req, res, next) { var id = req.payload._id; Post.find(function (err, posts) { if (err) { return next(err); } // This is a forEach that waits until all posts are populated before moving on async.each(posts, function (currentPost, postCallback) { currentPost.populate("author", function (err, post) { if (err) { return postCallback(err); } post.image = cloudinary.image("v" + post.author.avatarVersion + "/profile/" + post.author._id, { width: 100, height: 100, crop: 'thumb', gravity: 'face', radius: 'max' }); // the callback function for the current post postCallback(); }); }, function (error) { // the final callback function once all postCallback()'s have been executed, or an error if (error) { return next(error); } // here, everything is finished res.json(posts); }); }); }); 

同样,丹的解决scheme是正确的,所以不要使用这个代码。 当你遇到像这样的问题时,记住这一点。