$(document) 中的无限循环。与 API 接口时准备就绪

Infinite loop in $(document).ready when interfacing with API

我在这个项目上使用了 CodePen,这就是我发现我的代码中存在无限循环的原因。顺便说一句 - 它估计无限循环的行号为第 0 行,这就是为什么我怀疑它与 $(document).ready() 段代码有关。

我是 jQuery / API 初学者,如果这很明显,我们深表歉意。

代码如下:

$(document).ready(function() {
  var key = '*****************';
  var i = 0;
  var hotArray = [];

  function isInArray(value, array) {
    return array.indexOf(value) > -1;
  }

  function getMusic() {
    $.getJSON('http://developer.echonest.com/api/v4/song/search?api_key=' + key + '&artist=led+zeppelin&sort=song_hotttnesss-desc&results=50&bucket=song_hotttnesss', function(data) {
      while ($('.songs li').length < 10) {
        if (!(isInArray(data.response['songs'][i]['hotttnesss'], hotArray))) {
          $('.songs').append('<li>' + data.response['songs'][i]['title'] + '</li>');
          hotArray.push(data.response['songs'][i]['hotttnesss'])
        }
      }
      i++;
    });
  };

  $('.click').click(getMusic);
});

代码简要说明:

当我点击页面的特定位置(稍后将扩展为用户输入的艺术家)时,我试图获得 Led Zeppelin 的前 10 首歌曲。但是 Echo Nest API 的工作方式会返回很多很多重复项。例如,"Stairway to Heaven" 和 "Stairway To Heaven" 被认为是两首不同的歌曲。

为了解决这个问题,我使用了每首歌曲的 "hotttnesss" 值,这对于每首歌曲都是唯一的。同一位艺术家的两首歌曲具有相同热度的唯一方法是它们实际上是同一首歌曲,就像这些重复的歌曲一样。

因此,当报告的歌曲数量低于 10 首时,我将逐步检查每首返回的歌曲,如果歌曲的 hotttnesss 值不在已报告歌曲的 hotttnesss 值的数组中,则报告该歌曲.上报歌曲后,将歌曲的hotttnesss值添加到数组中

i++; 应该在 内部 while 循环中,而不是在它之后。您还需要在 ajax 回调中将 i 设置为 0,并将同一循环限制为 i < data.response['songs'].length.

例如:

function getMusic() {
    $.getJSON('http://developer.echonest.com/api/v4/song/search?api_key=' + key + '&artist=led+zeppelin&sort=song_hotttnesss-desc&results=50&bucket=song_hotttnesss', function(data) {
        var i, songs = data.response['songs'];
        for (i = 0; $('.songs li').length < 10 && i < songs.length; ++i) {
            if (!(isInArray(songs[i]['hotttnesss'], hotArray))) {
                $('.songs').append('<li>' + songs[i]['title'] + '</li>');
                hotArray.push(songs[i]['hotttnesss'])
            }
        }
    });
}

或者我直接使用Array#forEach(如果你需要支持IE8,你可以填充它):

function getMusic() {
    $.getJSON('http://developer.echonest.com/api/v4/song/search?api_key=' + key + '&artist=led+zeppelin&sort=song_hotttnesss-desc&results=50&bucket=song_hotttnesss', function(data) {
        data.response['songs'].forEach(function(song) {
            if (!(isInArray(song['hotttnesss'], hotArray))) {
                $('.songs').append('<li>' + song['title'] + '</li>');
                hotArray.push(song['hotttnesss'])
            }
        });
    });
}

旁注:

  1. 函数声明(比如你的getMusic)不是语句,你不需要语句终止符(; ) 在他们之后。 (你在一个函数 expression 之后做,也就是说,这是一个赋值的一部分。)

  2. song['hotttnesss']可以写成song.hotttnessresponse['songs']response.songs等,除非属性名字以数字开头或包含在 JavaScript 标识符名称中无效的字符,因此无需引用它。

  3. 在大多数情况下,将 () 放在函数调用周围没有任何意义,因此

    if (!(isInArray(song['hotttnesss'], hotArray))) {
    

    可以更清楚

    if (!isInArray(song['hotttnesss'], hotArray)) {
    

    (唯一有意义的时候涉及 inline-invoked 函数表达式。)

  4. 您不需要 isInArray 功能; jQuery 已有一个:$.inArray。 (从头到尾通读 jQuery API 非常值得。实际上只需要一两个小时,您会发现各种您可能不知道的有用信息。)