0

Here is a snippet from my express.js file:

function playlistTracks(req, res) {
var tracks = [];
var genres = ['hi'];

var playlistOption = {
    url: 'https://api.spotify.com/v1/users/' + req.params.user + '/playlists/'+ req.params.id + '/tracks',
    headers: { 'Authorization': 'Bearer ' + access_token },
    json: true
};

rp(playlistOption)
    .then(function (body) {
        tracks = body;
        return tracks;
    })
    .then(function (tracks) {
        getGenre(tracks);
        res.render('tracks', {
            data: tracks
        });
    })
    .catch(function (err) {
        console.log('couldnt get tracks' , err);
        throw err;
    });

function getGenre(tracks) {
    tracks.items.forEach(function(e){
        var reqGenre = {
            url: 'https://api.spotify.com/v1/artists/' + e.track.album.artists[0].id,
            json: true
        };

        rp(reqGenre)
            .then(function(body) {
                genres.push(body.genres)
            })
            .catch(function(err){
                console.log('couldnt get genres' , err);
                throw err
            });
    });

    io.emit('playlists', {genres: genres});
    console.log(genres) // <---empty 
}

}

the "getGenre" function is where I have the most trouble with. I want to know how I can update the "genres" array with that function. I've tried a couple of solutions but can't seem to get my head around the async nature of a request.

I've looked at this and other solutions already, but can't figure out how to apply them to my code.

I'm using request-promise to get the api request.

Community
  • 1
  • 1
olli208
  • 323
  • 2
  • 10
  • Your original sequence doesn't wait for getGenre to finish. To fix the issue, you could make getGenre return a promise that you fulfill once all the genres have been pushed. You are in for much re-ordering of your code, and probably using map and reduce to wrap fetches into promises. Try googling "promise array sequential" – Harry Pehkonen May 18 '17 at 20:21

1 Answers1

0

getGenre fetches data async, so you can try such code:

function playlistTracks(req, res) {
  var tracks = [];

  var playlistOption = {
      url: 'https://api.spotify.com/v1/users/' + req.params.user + '/playlists/'+ req.params.id + '/tracks',
      headers: { 'Authorization': 'Bearer ' + access_token },
      json: true
  };

  rp(playlistOption)
    .then(function (body) {
        tracks = body;
        return tracks;
    })
    .then(function (tracks) {
        getGenre(tracks);    
        
        res.render('tracks', {
            data: tracks
        });
    })
    .catch(function (err) {
        console.log('couldnt get tracks' , err);
        throw err;
    });

  function getGenre(tracks) {
      var promises = tracks.items.map(function(e){
        var reqGenre = {
          url: 'https://api.spotify.com/v1/artists/' + e.track.album.artists[0].id,
          json: true
        };

        return rp(reqGenre)
          .then(function(body) {
            return body.genres
          })
          .catch(function(err){
            console.log('couldnt get genres' , err);
            throw err
          });
      });
      
      return Promise.all(promises).then(function(results) {
        var genres = ['hi'].concat(results);
        io.emit('playlists', {genres: genres});
        console.log(genres)
      });
  }
}
lunochkin
  • 684
  • 4
  • 17