Last.FM API - 跟踪持续时间未定义

时间:2018-04-03 08:38:08

标签: javascript jquery ajax api

所以我尝试使用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

2 个答案:

答案 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