0

I am trying to create a helper file that will return the top track(s) of any artist's related artists. All I want to do use 1 artist URI to surface their related artists' name, popularity, and top track. And I want to separate out the top track functionality into a separate file that I can call whenever.

But, I can't seem to figure out how to properly return the top track of the related artists.

In my "get-toptrack.js" file:

   require([
      '$api/models',
      '$api/toplists#Toplist'
    ], function(models, Toplist) {
      'use strict';

      var doGetTopTrack = function(uri, num) {
        var artistURI = uri;
        var artist = models.Artist.fromURI(artistURI);
        var artistTopList = Toplist.forArtist(artist);

        artistTopList.tracks.snapshot().done(function(snapshot){

          snapshot.loadAll('name').done(function(tracks) {
            var i, num_toptracks;
            num_toptracks = num;

              for(i = 0; i < num_toptracks; i++){
                console.log("top track: " + tracks[i].name);
                // WHERE DO I RETURN THE TOP TRACKS??
              }
          });
        });
      };

      exports.doGetTopTrack = doGetTopTrack;
    });

In my "artist.js" file":

require([
    '$api/models',
    'scripts/get-toptrack'
  ], function(models, getTopTrack) {
    'use strict';

    var showRelated = function() {
      var artist_properties = ['name', 'popularity','related', 'uri'];

      models.Artist
        .fromURI('spotify:artist:11FY888Qctoy6YueCpFkXT')
        .load(artist_properties)
        .done(function(artist){

          artist.related.snapshot().done(function(snapshot){
            snapshot.loadAll('name').done(function(artists) {

              for(var i = 0; i < artists.length; i++){
                var u, p, n, t, listItem;

                // store artist details
                p = artists[i].popularity;
                n = artists[i].name;
                u = artists[i].uri;

                // am I missing something here?
                t = getTopTrack.doGetTopTrack(u, 1);

                listItem = document.createElement("li");
                listItem.innerHTML = "<strong>Name</strong>: " + n.decodeForText() + " | <strong>Popularity: </strong> " + p + " | <strong>Top Track: </strong>" + t;

                // undefined name
                $('#artistsContainer').append(listItem);

              }
            });

          });
        });
    };

    exports.showArtists = showArtists;
  });

And in the 'main.js' file, I call the artists function to begin.

require([
  '$api/models',
  'scripts/artist'
], function(models, initArtist) {
  'use strict';

  initArtist.showRelated();
});
Thomas
  • 3,348
  • 4
  • 35
  • 49
cusejuice
  • 10,285
  • 26
  • 90
  • 145

1 Answers1

1

can't comment on the multiple .js files as I haven't yet refactored my app into multiple files.

As far as returning goes, you're working in an asynchronous application, so you can't. You have to use a callback, or a Spotify Promise might make your api more congruous with Spotify's. Look at the documentation for Promise.each().

Here is an implementation of the callback method. Changed a few things to make it easier for me to test. Made life a bit easier to pass the artist in instead. Also, there is no guarantee of the order they will come out since the second artist's toplist could come back faster than the first. You'll need to add more code if you want to keep order.

function doGetTopTrack(artist, num, callback) {
    var artistTopList = Toplist.forArtist(artist);

    artistTopList.tracks.snapshot(0,num).done(function (snapshot) { //only get the number of tracks we need

        snapshot.loadAll('name').done(function (tracks) {
            var i, num_toptracks;
            num_toptracks = num; //this probably should be minimum of num and tracks.length

            for (i = 0; i < num_toptracks; i++) {
                callback(artist, tracks[i]);
            }
        });
    });
};

function showRelated() {
    var artist_properties = ['name', 'popularity', 'related', 'uri'];

    models.Artist
      .fromURI('spotify:artist:11FY888Qctoy6YueCpFkXT')
      .load(artist_properties)
      .done(function (artist) {

          artist.related.snapshot().done(function (snapshot) {
              snapshot.loadAll('name').done(function (artists) {

                  for (var i = 0; i < artists.length; i++) {
                      // am I missing something here?
                      doGetTopTrack(artists[i], 1, function (artist, toptrack) {
                              console.log("top track: " + toptrack.name);

                              var p = artist.popularity;
                              var n = artist.name;
                              var u = artist.uri;

                              //listItem = document.createElement("li");
                              console.log("<strong>Name</strong>: " + n.decodeForText() + " | <strong>Popularity: </strong> " + p + " | <strong>Top Track: </strong>" + toptrack.name);

                              //// undefined name
                              //$('#artistsContainer').append(listItem);
                      });
                  }
              });

          });
      });
};
showRelated();
Thomas
  • 3,348
  • 4
  • 35
  • 49
  • Thank you for this. Explains alot! – cusejuice Nov 04 '13 at 15:41
  • Is there a particular reason to retain 'order' from grabbing the tracks? If so, can you point me in the right direction of what to look up in the Spotify Docs? – cusejuice Nov 04 '13 at 15:43
  • In this case, I don't see any reason to maintain order. But if you really wanted to make sure your artist list entries were in the same order as 'related', then you'd need to redo to logic to store each track and output them all at the end. – Thomas Nov 04 '13 at 15:50
  • If I wanted to create a 'list' of these top tracks, would I have to completely refactor my code above? – cusejuice Nov 05 '13 at 02:12
  • http://stackoverflow.com/questions/19781876/spotify-api-create-temp-playlist-not-loading – cusejuice Nov 05 '13 at 04:31