Jquery 延迟 & 每个循环

Jquery Defer & Each Loop

我对 JSON 和 Deferrers 有点陌生,所以很抱歉答案很明显。

我正在使用 pokeapi.co 并尝试使用 getJSON 提取各种口袋妖怪的详细信息。我创建了一个函数,它接受一个 URL 数组,运行一个 getJSON 函数从 URL 中提取数据,遍历数据并将其推入一个数组。我正在尝试使用延迟对象并承诺确定何时完成所有操作,以便我可以在另一个函数中使用数据。不幸的是,我似乎做错了什么。

var url = [
  "http://pokeapi.co/api/v2/pokemon/1/",
  "http://pokeapi.co/api/v2/pokemon/2/"
];

function getPokemonDetails(url){
  var def = $.Deferred();
  var promises = [];
  var pokemon;
  $.each(url, function(i, index){
    var deferred = $.Deferred();
    $.getJSON(index, function(data){
      pokemon = [data.name, data.stats];
      var abilityURLs = [];
      $.each(data.abilities, function(a, abilities){
        abilityURLs.push(abilities.ability.url)
      });

      pokemon.push(abilityURLs);
      deferred.resolve(pokemon);
    }); //End getJSON

    deferred.done(function(data){
      promises.push(data);
      console.log(promises);
    })// End Deferred
  }); //End Each

  $.when(...promises).done(function(){
    console.log(arguments.length);
  });
}

getPokemonDetails(url);

目前,当 console.log 运行时,我希望 promises 数组的长度为 2,但目前它 returns 0。我不确定我到底在哪里出错了。

首先,不要使用 $.each 和推送,因为你有一个从源数组到目标数组的 1:1 映射,你应该使用 Array.prototype.map.

其次,由于 $.getJSON 已经 returns 一个 $.Deferred(),因此绝对没有必要创建自己的一个。

因此,如果我正确地遵循您当前的代码,它可以完全替换为:

function getPokemonDetails(url_list) {
    return $.when(... url_list.map(url =>
        $.getJSON(url).then(
            data => [ data.name, data.stats, [
                data.abilities.map(ability => ability.ability.url)
            ]]
        )
    ));
}

内部 .then 调用获取每个 AJAX 调用返回的数据和 returns 解析为名称数组、统计数据和嵌套能力数组的承诺。

尽管如此,我可能会将其分为两个函数 - 一个处理单个 URL,另一个处理多个:

const getPokemonDetails = url => $.getJSON(url).then(
    data => [ data.name, data.stats, [
                data.abilities.map(ability => ability.ability.url)
            ]]);

const getMultiPokemonDetails = list => $.when(...list.map(getPokemonDetails));