这是我的代码:
server.get(url_prefix + '/user/:user_id/photos', function(req, res, next) {
if (!req.headers['x-session-id']) {
res.send({
status: {
error: 1,
message: "Session ID not present in request header"
}
})
} else {
User.findOne({
session_id: req.headers['x-session-id']
}, function(err, user) {
if (user) {
var user_id = req.params.user_id
Album.find({userId : user_id})
.populate('images')
.exec(function (err, albums) {
if (albums) {
albums.forEach(function(album, j) {
var album_images = album.images
album_images.forEach(function(image, i) {
Like.findOne({imageID : image._id, userIDs:user._id}, function(err,like){
if(like){
albums[j].images[i].userLike = true;
}
})
})
})
return res.send({
status: {
error: 0,
message: "Successful"
},
data: {
albums: albums
}
})
} else
return notify_error(res, "No Results", 1, 404)
})
}
else {
res.send({
status: {
error: 1,
message: "Invalid Session ID"
}
})
}
})
}
})
我正在尝试为我的图片数组添加一个额外的值(albums[j].images[i].userLike = true;
),该数组位于相册数组中。
问题是return res.send({
在我们收到来自foreach的回复之前发送数据
如何使其工作,以便只有在foreach完成所有迭代后return
才会发生
答案 0 :(得分:4)
您必须等待调用res.send
,直到您获取每张相册中所有图片的所有相似内容。 E.g。
var pendingImageLikes = album_images.length;
album_images.forEach(function(image, i) {
Like.findOne({imageID : image._id, userIDs:user._id}, function(err,like){
if (like) {
albums[j].images[i].userLike = true;
}
if (!--pendingImageLikes) {
// we fetched all likes
res.send(
// ...
);
}
});
您可能需要album_images.length === 0
的特殊情况。
此外,这并没有考虑到您有多张相册,每张相册都有多张图片。您必须以非常类似的方式延迟res.send
才能使其真正起作用。您可能需要考虑使用流程控制库,如first(或您的任何其他偏好,只需搜索“流控制库”),以使这更容易。
此外,您可能需要考虑不依赖分号插入并手动键入分号。它可以防止模糊表达,使代码更容易阅读。
答案 1 :(得分:2)
由于您需要等待代码完成所有find
操作,我建议您考虑使用async包,特别是each
({{{ 3}})。它使得使用异步循环更清晰,尤其是在处理MongoDB文档和查询时。有许多不错的功能,包括顺序执行reference函数或series的功能(当你想执行一系列,但是逐步传递结果时)。
> npm install async
添加到您的模块:
var async = require("async");
您的代码看起来像这样:
albums.forEach(function(album, j) {
async.each(album.images, function(album, done) {
Like.findOne({imageID: image._id, userIDs:user._id}, function(err, like){
if(!err && like){
albums[j].images[i].userLike = true;
}
done(err); // callback that this one has finished
})
})
}, function (err) { // called when all iterations have called done()
if (!err) {
return res.send({
status: {
error: 0,
message: "Successful"
},
data: {
albums: albums
}
});
}
return notify_error(res, "No Results", 1, 404);
});
});