我正在制作一个小应用程序,显示艺术家相关艺术家的首首歌曲列表。当我第一次尝试加载我的应用程序时,它什么也没显示。但是,当我“重新加载应用程序”时,一切似乎都有效。当我不断开始“重新加载”时,它会不断添加更多相同的曲目到列表中。
如何阻止它不断地将更多曲目添加到列表中以及收紧代码以使其在加载时正常工作?
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');
});
答案 0 :(得分: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');
});
答案 1 :(得分:2)
我想到这样的事情的方式是想象我是一个超级慢的连接。如果每个回调(完成或传递给getTopTrack的函数)花了2秒钟来响应,我如何构建我的代码来处理它?</ p>
这在哪里适用?好吧,当你调用buildList时,temp实际上是空的。我怀疑你是否先在getRelated中创建了播放列表,然后在你的getTopTrack回调中添加了歌曲,那么它会起作用,因为List会让自己保持最新状态。
或者,您可以返工getTopTrack返回Promise,将所有顶级轨道承诺连接在一起(请参阅每个()上的Promise doc和join()),然后在它们全部完成时构建列表。
至于为什么要获得多个列表,这是因为每次调用buildList时都会追加一个新的List。虽然当我把代码扔到我的游乐场区域时,我没有看到这种行为。它只发生一次,当我重新加载应用程序时,它从头开始。也许你有一个重新加载按钮,它正在调用getRelated。
更新我一直试图让这个工作,并遇到很多麻烦。每次添加后尝试调用list.refresh。现在尝试使用基于Promise的方法,但仍无法让List显示任何内容。