Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

forEach with NodeJS and Async

I am new to NodeJS(Express). I am trying to build an API that will list the "Rooms" of a Hotel, and "Photos" for each room.

What I am trying to do is: - get a list of all rooms by a hotel - loop through this list of rooms and add photos - return JSON with rooms and photos

My problem is that I can not seem to attach the "photos" result to the "rooms result.

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);

});

Any help would be greatly appreciated, as I have been hours trying to figure it out.

Thanks

Ray


I have updated my script to this, but the "photos" are still not going into the final "rooms" object. I have included the code and also the console output.

Code:

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);
            }
        })      
    });
};

Here is the console output for the above script:

Room Name: Test Room 1

Room Name: Test Room 2

Photos:

{ _id: 5acd3094e0026f38ca4b44bc,
  src: 'https://picsum.photos/200/300/?image=252',
  room: 5acd3094e0026f38ca4b44bb,
  __v: 0 }

Photos:

{ _id: 5acd30c8cec87777eefcd32d,
  src: 'https://picsum.photos/200/300/?image=252',
  room: 5acd30c8cec87777eefcd32c,
  __v: 0 }

FINAL ROOMS OBJECT

[ { _id: 5acd3094e0026f38ca4b44bb,
    name: 'Test Room 1',
    hotel: 5accd4e1734d1d55c3195c84,
    __v: 0 },
  { _id: 5acd30c8cec87777eefcd32c,
    name: 'Test Room 2',
    hotel: 5accd4e1734d1d55c3195c84,
    __v: 0 } ]
like image 470
Ray Phelan Avatar asked Aug 13 '26 18:08

Ray Phelan


1 Answers

Since the function RoomPhoto is also asynchronous, then you need to wait until all the photos are loaded before calling the callback function. Like that:

//  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)
    })
}
like image 137
stdob-- Avatar answered Aug 16 '26 07:08

stdob--



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!