我是NodeJS(Express)的新手。我正在尝试构建一个API,列出酒店的“房间”,以及每个房间的“照片”。
我想做的是: - 获取酒店所有客房的清单 - 循环浏览此房间列表并添加照片 - 返回带有房间和照片的JSON
我的问题是我似乎无法将“照片”结果附加到“房间结果”。
async.waterfall([
// Function 1
function(callback) {
// Find all Hotel Rooms
Room.find({ 'hotel': req.params.hotel_id})
.exec(function(err, rooms) {
callback(null, rooms); // Send rooms to function 2
});
},
// Function 2
function(rooms, callback) {
// Loop through each room to get photos for each room
rooms.forEach(function(room) {
// Get photos for room
RoomPhoto.find({ 'room': room._id})
.exec(function(err, photos) {
// I want to add these "photos" to the main "rooms" object, but attached to each individual "room"
room.photos = JSON.stringify(photos);
});
})
console.log(rooms)
callback(null, rooms);
}
], function(err, results) {
if(err) console.log('err');
res.json(results);
});
任何帮助都会非常感激,因为我已经花了好几个小时试图解决它。
由于
雷
我已将我的脚本更新为此,但“照片”仍未进入最终的“房间”对象。我已经包含了代码以及控制台输出。
代码:
exports.index = function(req, res, next) {
Room.find({ 'hotel': req.params.hotel_id})
.exec(function(err, rooms) {
async.each(rooms, function(room, room_cb) {
console.log('Room Name: ' + room.name);
RoomPhoto.find({ 'room': room._id})
.exec(function(err, photos) {
console.log('Photos: ' + photos);
room.photos = photos;
// photos should now be in the main "rooms" object right??
// I can console.log the photos here to prove they exists
room_cb();
});
}, function(err) {
if(err) {
console.log('Error: ' + err)
}
else {
// But the photos are not in the final "rooms" object
console.log('FINAL ROOMS OBJECT, why are the photos not here??');
console.log(rooms);
res.json(rooms);
}
})
});
};
以下是上述脚本的控制台输出:
房间名称:测试室1
房间名称:测试室2
照片:
{ _id: 5acd3094e0026f38ca4b44bc, src: 'https://picsum.photos/200/300/?image=252', room: 5acd3094e0026f38ca4b44bb, __v: 0 }
照片:
{ _id: 5acd30c8cec87777eefcd32d, src: 'https://picsum.photos/200/300/?image=252', room: 5acd30c8cec87777eefcd32c, __v: 0 }
最终房间对象
[ { _id: 5acd3094e0026f38ca4b44bb, name: 'Test Room 1', hotel: 5accd4e1734d1d55c3195c84, __v: 0 }, { _id: 5acd30c8cec87777eefcd32c, name: 'Test Room 2', hotel: 5accd4e1734d1d55c3195c84, __v: 0 } ]
答案 0 :(得分:4)
由于函数RoomPhoto
也是异步的,因此您需要等到所有照片都加载后再调用回调函数。像那样:
// Function 2
function(rooms, callback) {
// https://caolan.github.io/async/docs.html#each
// Loop through each room to get photos for each room
async.each(rooms, function(room, room_cb) {
// Get photos for room
RoomPhoto.find({ 'room': room._id})
.exec(function(err, photos) {
room.photos = JSON.stringify(photos)
room_cb()
});
}, function (err) {
console.log(rooms)
callback(null, rooms)
})
}
答案 1 :(得分:0)
由于您是node.js
的新用户,您可能不了解最新标准以及您可以使用的内容。以下是如何在不包含async
模块的情况下完成此任务... < / p>
const requestHandler = async (req, res, next) => {
let rooms = await Room.find({ 'hotel': req.params.hotel_id})
.exec()
.catch(err => {
console.log(err);
throw err;
});
// Get photos for room
let photos = await Promise.all(rooms.map(
room => RoomPhoto.find({ 'room': room._id})
.catch(err => {
console.log(err);
throw err;
});
))
rooms = rooms.map((room, index) => {
room = room.toObject();
room.photos = JSON.stringify(photos[index]);
return room;
});
// Now your "rooms" array will have room objects, with photos populated.
res.send(rooms);
});
要导出它,您可以这样做:
module.exports.index = requestHandler;
答案 2 :(得分:0)
我找到了有效的东西...... 出于某种原因,MongoDB“_id”导致了问题。
exports.index = function(req,res,next){
Room.find({ 'hotel': req.params.hotel_id})
.exec(function(err, rooms) {
rooms = JSON.parse(JSON.stringify(rooms).replace(/_id/g,"room_id"));
console.log(rooms);
console.log('---------------------------');
async.each(rooms, function(room, room_cb) {
RoomPhoto.find({ 'room': room.room_id})
.exec(function(err, photos) {
console.log('Room: ' + room.id);
console.log('Photos: ' + photos);
room.photos = photos;
//console.log('Photos: ' + rooms[key].photos);
room_cb();
});
}, function(err) {
if(err) {
console.log('Error: ' + err)
}
else {
console.log('FINAL ROOMS OBJECT');
rooms = JSON.parse(JSON.stringify(rooms).replace(/room_id/g,"_id"));
console.log(rooms);
res.json(rooms);
}
})
});
};
答案 3 :(得分:-1)
尝试在callback(null, rooms);
行下方放置第二条room.photos = JSON.stringify(photos);
行(靠近末尾的行)。
由于JavaScript的异步特性,它可能会在您的查询完成获取照片之前运行。
您可能还想添加一些支票,以防房间没有照片。