3

アーティストの関連アーティストの最初の曲のトップのリストを表示する小さなアプリを作成しています。初めてアプリを読み込もうとすると、何も表示されません。しかし、「アプリケーションをリロード」すると、すべてがうまくいくようです。常に「リロード」を開始すると、同じトラックがリストに追加され続けます。

ロード時に動作するようにコードを引き締めるだけでなく、リストにトラックを継続的に追加するのを止めるにはどうすればよいですか?

require([
  '$api/models',
  '$views/list#List',
  '$api/toplists#Toplist'

  ], function(models, List, Toplist){
    'use strict';

  // Build playlist
  function buildList(trackURIArray){
    var arr = trackURIArray;
    models.Playlist
      .createTemporary("myTempList")
      .done(function(playlist){ 
        playlist.load("tracks").done(function(loadedPlaylist){
          for(var i = 0; i < arr.length; i++){
            loadedPlaylist.tracks.add(models.Track.fromURI(arr[i]));
          }
        });

        // Create list
        var list = List.forPlaylist(playlist,{
          style:'rounded'
        });

        $('#playlistContainer').append(list.node);
        list.init();
      });
  }

  // Get top track
  function getTopTrack(artist, num, callback){
    var artistTopList = Toplist.forArtist(artist);

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

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

  // Get Related
  function getRelated(artist_uri){
    var artist_properties = ['name', 'popularity', 'related', 'uri'];

    models.Artist
    .fromURI(artist_uri)
    .load(artist_properties)
    .done(function (artist){

      artist.related.snapshot().done(function(snapshot){
        snapshot.loadAll('name').done(function(artists){
          var temp = [];

          for(var i = 0; i < artists.length; i++){

            getTopTrack(artists[i], 1, function(artist, toptrack){
              var p, n, u;

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

              temp.push(toptrack.uri);

            });
          }
          // Build a list of these tracks
          buildList(temp);
        });
      });
    });
  }

  getRelated('spotify:artist:2VAvhf61GgLYmC6C8anyX1');
});
4

2 に答える 2

7

Promisesを使用すると、トラックを含む一時リストが正常に作成されるまで、リストのレンダリングを遅らせることができます。また、リロード時に繰り返しトラックが追加されるのを防ぐために、一時プレイリストに一意の名前を割り当てます。

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

  // Build playlist
  function buildList(trackURIArray) {
    var arr = trackURIArray;
    models.Playlist
      .createTemporary("myTempList_" + new Date().getTime())
      .done(function (playlist) {
        playlist.load("tracks").done(function () {
          playlist.tracks.add.apply(playlist.tracks, arr).done(function () {
            // Create list
            var list = List.forCollection(playlist, {
              style: 'rounded'
            });

            $('#playlistContainer').appendChild(list.node);
            list.init();
          });
        });
      });
  }

  // Get top track
  function getTopTrack(artist, num) {
    var promise = new models.Promise();
    var artistTopList = Toplist.forArtist(artist);

    artistTopList.tracks.snapshot(0, num).done(function (snapshot) {
      snapshot.loadAll().done(function (tracks) {
        promise.setDone(tracks[0]);
      }).fail(function (f) {
        promise.setFail(f);
      });
    });

    return promise;
  }

  // Get Related
  function getRelated(artist_uri) {
    models.Artist
      .fromURI(artist_uri)
      .load('related')
      .done(function (artist) {
        artist.related.snapshot().done(function (snapshot) {
          snapshot.loadAll().done(function (artists) {

            var promises = [];

            for (var i = 0; i < artists.length; i++) {
              var promise = getTopTrack(artists[i], 1);
              promises.push(promise);
            }

            models.Promise.join(promises)
              .done(function (tracks) {
                console.log('Loaded all tracks', tracks);
              })
              .fail(function (tracks) {
                console.error('Failed to load at least one track.', tracks);
              })
              .always(function (tracks) {
                // filter out results from failed promises
                buildList(tracks.filter(function(t) {
                  return t !== undefined;
                }));
              });
          });
        });
      });
  }

  getRelated('spotify:artist:2VAvhf61GgLYmC6C8anyX1');
});
于 2013-11-06T22:51:21.953 に答える
2

このようなことについて私が考える方法は、私が非常に遅い接続にいると想像することです. すべてのコールバック (完了、または getTopTrack に渡された関数) の応答に 2 秒かかった場合、それを処理するためにコードをどのように構築する必要がありますか?

それはここでどのように適用されますか?buildList を呼び出すと、temp は実際には空です。最初に getRelated でプレイリストを作成し、次に getTopTrack のコールバックでプレイリストに曲を追加すると、List 自体が最新の状態に保たれるため、機能するのではないかと思います。

別の方法として、getTopTrack を作り直して Promise を返し、すべての上位トラックの promise を結合し (each() および join() に関する Promise のドキュメントを参照)、それらがすべて完了したらリストを作成することもできます。

複数のリストを取得する理由は、buildList を呼び出すたびに新しいリストを追加するためです。コードをそのままプレイグラウンドエリアに投げたとき、この動作は見られませんが。一度だけ発生し、アプリケーションをリロードすると最初から開始されます。おそらく、getRelated を呼び出しているリロード ボタンがあります。

更新私はこれを機能させようとしてきましたが、多くの問題を抱えています。追加するたびに list.refresh を呼び出してみました。現在、Promise ベースのメソッドを試していますが、リストに何も表示できません。

于 2013-11-05T14:51:20.920 に答える