0

I'm trying to save some objects into an array by looping through a list of songs in an album, looking for relevant songs and trying to save into array for later use. is there any way to achieve this?

I need some explanation using mongoose.

exports.playlistPlayer = function (req, res, next) {
Playlist.findById({
    _id: req.body.playlist._id
}, (err, playlist) => {

    var customAlbum = []; //This variable it's inside the same block i believe


    playlist.songs.forEach(function (song) {
        Song.findById({
            _id: song.song_id
        }, (err, songs) => {

            var customSong = {
                title: songs.title,
                time: songs.time,
                source: songs.source,
                song_id: songs._id
            }
            customAlbum.push(customSong)
            console.log(customAlbum) //it works here
        });

    });

    console.log(customAlbum) //it returns an empty array here where i need the data

 });
};
avide
  • 21
  • 4
  • 3
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Patrick Hund Oct 01 '17 at 21:33
  • @PatrickHund Can you tell me how it help me?, can't find the solution yet. – avide Oct 01 '17 at 21:52

1 Answers1

0

The problem is that the findById method is also asynchronous. I recommend you to learn about promises in javascript. One possible solution would be using the async/await feature from ES7:

// asynchronous function
exports.playlistPlayer = async (req, res, next) => {
  // wait for the findById method promise to resolve
  const playlist = await Playlist.findById({
    _id: req.body.playlist._id
  })

  // wait for finding all songs in db whose id's are in
  // the playlist.songs array
  const songs = await Song.find({
    _id: { $in: playlist.songs }
  })

  // create the customAlbum by using the map method to
  // tramsform the song objects to the required form
  const customAlbum = songs.map(song => ({
    title: song.title,
    time: song.time,
    source: song.source,
    song_id: song._id
  }))

  // and there you should now have your customAlbum array
  console.log(customAlbum)

  // now you can use it for example
  // to return a response to the client:
  // res.json(customAlbum)
}
dkanas
  • 51
  • 5
  • Updated node to the latest version and fixed an issue where the playlist schema were saving objects instead of the id. Thank you very much for this information, the only part i can't figure out how to make it work is this const customAlbum = songs.map(song => ({ title: song.title, time: song.time, source: song.source, song_id: song._id }) – avide Oct 01 '17 at 22:44
  • Need a bit more info about this - is that line of code not working? – dkanas Oct 01 '17 at 22:50
  • It isn't working, it tells me theres a syntax error in that line. – avide Oct 01 '17 at 23:26
  • Oh, sorry, I missed a closing brace - it should be `const customAlbum = songs.map(song => ({ title: song.title, time: song.time, source: song.source, song_id: song._id }))` – dkanas Oct 01 '17 at 23:30
  • Just noticed it, man thank you a lot! you saved my project for tomorrow. – avide Oct 01 '17 at 23:32
  • Happy to help! :D – dkanas Oct 01 '17 at 23:47