Jquery Defer&每个循环

时间:2017-06-26 15:57:28

标签: jquery promise getjson jquery-deferred

我对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,但此刻它返回0.我不确定我到底出错了。

1 个答案:

答案 0 :(得分:1)

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

其次,由于$.getJSON已经返回$.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调用返回的数据,并返回一个promise,该promise将解析为name,stats和嵌套数组的数据。

对于它的价值,我可能会把它分成两个函数 - 一个处理单个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));