所以我尝试使用Last.fm API为自己创建一个小应用。
我现在遇到的问题是,当我请求跟踪持续时间时,我可以成功将其登录到控制台并从开发工具中附加它,但是在DOM本身的第一次运行中它只会吐出未定义或NaN(如果我使用parseFloat)。
我的ajax请求缓慢是,从API获取数据然后再在DOM上呈现它? 如果是的话,可能的解决方案是什么?或者向正确的方向推进去看看会很甜蜜。
这是我的jQuery代码:
var Trackster = {};
const API_KEY = '1234';
var trackResults;
var trackDuration;
$(document).ready(function() {
$("#submitButton").click(function() {
Trackster.searchTracksByTitle($("#inputField").val());
$('#detailContainer').empty();
})
})
/*
Given an array of track data, create the HTML for a Bootstrap row for each.
Append each "row" to the container in the body to display all tracks.
*/
Trackster.renderTracks = function(tracks) {
for (var i = 0; i <= (trackResults.length)-1; i++) {
var mediaAlbumArt = trackResults[i].image[1]["#text"];
$.ajax({
url: 'https://ws.audioscrobbler.com/2.0/?
method=track.getInfo&
api_key='+API_KEY+'&artist='
+ trackResults[i].artist
+ '&track='
+ trackResults[i].name
+ '&format=json',
dataType: 'jsonp',
success: function(d) {
console.log("Success", d.track.duration);
trackDuration = d.track.duration;
},
error: function(err) {
console.log("Error", err);
}
})
var $tracks = '<div id="song-details" class="container-fluid">'+
'<div class="row align-items-center h-100">'+
'</div>'+
'<div class="col-md-1">'+
'<span>' + parseFloat(i+1) + '</span>'+
'</div>'+
'<div class="col-md-3">'+
'<span>' + trackResults[i].name + '</span>'+
'</div>'+
'<div class="col-md-2">'+
'<span>' + trackResults[i].artist + '</span>'+
'</div>'+
'<div class="col-md-2">'+
'<img src="' + mediaAlbumArt + '" />'+
'</div>'+
'<div class="col-md-1">'+
'<span>' + trackResults[i].listeners + '</span>'+
'</div>'+
'<div class="col-md-1" id="duration">'+
'<span>' + trackDuration + '</span>'
'</div>'+
'</div>'+
'</div>';
$('#detailContainer').append($tracks);
}
};
Trackster.searchTracksByTitle = function(title) {
$.ajax({
url: 'https://ws.audioscrobbler.com/2.0/?
method=track.search
&track='+($("#inputField").val())
+'&api_key='+API_KEY+'
&format=json',
dataType: 'jsonp',
success: function(data) {
console.log("Success!", data);
trackResults = data.results.trackmatches.track;
Trackster.renderTracks();
},
error: function(e) {
console.log("Error!", e);
}
})
};
我在循环中包含了ajax请求,因为我需要知道每首歌的持续时间以及我提出的解决方案。
这是在GitHub上运行的应用程序https://drood87.github.io/start/
希望有人可以给我一两个提示。 谢谢&lt; 3
答案 0 :(得分:1)
您正在将同步操作与异步操作混合使用。 $ .ajax异步工作,从该调用返回的数据不能立即供您处理。您可以在AJAX成功函数中移动追加,以使脚本使用持续时间数据。
或者,
您可以将数据与trackid相关联,并使用以下内容:
创建包含数据的行时:
'<div id="song-details-' + trackResults[i].mbid + '" class="container-fluid">' +
...
'<div class="col-md-1 duration">'
顺便说一句,您不能在同一文档中拥有具有相同ID的元素。它将打破局面。
然后在AJAX方面;
$.ajax({success(data){
$("#song-details-"+data.track.mbid).find(".duration").text(data.track.duration);
});
这样您就可以异步填充持续时间行。
答案 1 :(得分:0)
你的ajax不慢,你的代码组织不正确
查看获取ajax的曲目信息:
$.ajax({
url: 'https://ws.audioscrobbler.com/2.0/?
method=track.getInfo&
api_key='+API_KEY+'&artist='
+ trackResults[i].artist
+ '&track='
+ trackResults[i].name
+ '&format=json',
dataType: 'jsonp',
success: function(d) {
console.log("Success", d.track.duration);
trackDuration = d.track.duration;
},
error: function(err) {
console.log("Error", err);
}
})
在您的成功功能中,您正在设置trackDuration
,然后您正在创建一些HTML。你可以看到,在jj中,你的ajax
调用将在ajax的success
回调函数之前执行,你无法依赖该代码。要确保执行顺序,您需要将处理程序代码放在success
函数中。请查看返工renderTracks
函数
Trackster.renderTracks = function(tracks) {
let detailContainer = $('#detailContainer');
for (var i = 0; i <= (trackResults.length)-1; i++) {
var mediaAlbumArt = trackResults[i].image[1]["#text"];
((i) => $.ajax({
url: 'https://ws.audioscrobbler.com/2.0/?
method=track.getInfo&
api_key='+API_KEY+'&artist='
+ trackResults[i].artist
+ '&track='
+ trackResults[i].name
+ '&format=json',
dataType: 'jsonp',
success: function(d) {
console.log("Success", d.track.duration);
let trackDuration = d.track.duration;
var $tracks = '<div id="song-details" class="container-fluid">'+
'<div class="row align-items-center h-100">'+
'</div>'+
'<div class="col-md-1">'+
'<span>' + parseFloat(i+1) + '</span>'+
'</div>'+
'<div class="col-md-3">'+
'<span>' + trackResults[i].name + '</span>'+
'</div>'+
'<div class="col-md-2">'+
'<span>' + trackResults[i].artist + '</span>'+
'</div>'+
'<div class="col-md-2">'+
'<img src="' + mediaAlbumArt + '" />'+
'</div>'+
'<div class="col-md-1">'+
'<span>' + trackResults[i].listeners + '</span>'+
'</div>'+
'<div class="col-md-1" id="duration">'+
'<span>' + trackDuration + '</span>'
'</div>'+
'</div>'+
'</div>';
detailContainer.append($tracks);
},
error: function(err) {
console.log("Error", err);
}
}))(i)
}};
我已将您的跟踪HTML创建逻辑放在ajax的success
回调函数中 - 它确保HTML创建将在您的ajax的成功上发生
注意我在循环之前创建了let detailContainer = $('#detailContainer');
并且只进行了一次元素查找 - 这是你应该总是使用的优化
另请查看我如何使用ajax
包裹您的((i) => $.ajax ... )(i)
函数。这称为IIFE,它可以帮助您在每个i
调用中专门保存ajax
的值。您也可以使用let i
代替var i
和IFFY