只Push成功回调数据到数组,排除404错误

Only Push success callback data to array, exclude error 404

我在处理错误 404 时遇到问题。我想做的是,我想将通过向 PokeApi 发出请求获得的数据推送到一个数组中。如果对 API 的所有请求都成功并推入数组,一切正常,那么我就可以取出我想要的数据,将其移至我的 then() 并将其附加到 div。但是,一旦请求出现 404 错误未找到,我的 div 就不会附加任何内容。我如何处理 404 并继续循环并能够附加我的数据?

我已经尝试过,使用 if 语句和 fail()、done(),但没有按我想要的那样工作。

function get_sprites(poke_name){
 var arr = [];
 for(var i = 0; i<poke_name.length; i++){
     arr.push($.getJSON("https://pokeapi.co/api/v2/pokemon/" + 
     poke_name[i]));
 }
 $.when.apply($, arr).then(function(){
    var storeObjPoke = [];
    for(var i = 0; i < arguments.length; i++){
        var name = arguments[i][0].name
        var upperCase_name = name.charAt(0).toUpperCase() + 
        name.slice(1);
        var objPoke = {
        id : arguments[i][0].id,
        name : upperCase_name,
        imgUrl : arguments[i][0].sprites.front_default
      }
      $("<div class='pokemon' id='"+ arguments[i][0].id +"'>" + 
        upperCase_name + "<br><img src='" +arguments[i] 
        [0].sprites.front_default+"'alt=''/><br>" + arguments[i][0].id + 
       "</div>" ).appendTo("#display_pokemon");
    }
 }
}

我希望它能够在我的 div 中显示我的所有对象,但是当我收到 404 错误时,没有任何内容附加到 div。

所以看起来 .whenpromise.all 相似,事实上它是一个全有或全无的事情。必须解决(成功)所有承诺才能触发 .then 函数。

因此,一旦 404 的承诺被拒绝,jQuery 就会立即调用 .fail() 函数(你没有它,所以它会吞下错误)并且其余的承诺可能未实现,因此 .then() 未被调用。

来自 jQuery.when()

In the case where multiple Deferred objects are passed to jQuery.when(), the method returns the Promise from a new "master" Deferred object that tracks the aggregate state of all the Deferreds it has been passed. The method will resolve its master Deferred as soon as all the Deferreds resolve, or reject the master Deferred as soon as one of the Deferreds is rejected.

In the multiple-Deferreds case where one of the Deferreds is rejected, jQuery.when() immediately fires the failCallbacks for its master Deferred. Note that some of the Deferreds may still be unresolved at that point.

因此,如果没有一些额外的绒毛,您尝试做的事情似乎是不可能的。您可以查看此 SO 答案,以更全面地了解您可能需要的一些问题 including a future proposal promise. allSettled(),这可以解决您的问题,但目前仅与少数浏览器兼容。

2 个其他想法

  1. 在 UI 中开始显示之前等待所有请求返回是否重要?如果不是,则只需循环调用请求。

例如,

get_sprites(["squirtle", "charmander", "not_a_pokemon", "bulbasaur"])

function get_sprites(poke_name) {
  for (let i = 0; i < poke_name.length; i++) {
    $.getJSON("https://pokeapi.co/api/v2/pokemon/" + poke_name[i], addPokemon)
      .fail(function(err) {
        console.log(`error getting pokemon: ${poke_name[i]} - ${err.status}`);
      });
  }

  function addPokemon(pokemon) {
    var storeObjPoke = [];
    var name = pokemon.name
    var upperCase_name = name.charAt(0).toUpperCase() + name.slice(1);
    var objPoke = {
      id: pokemon.id,
      name: upperCase_name,
      imgUrl: pokemon.sprites.front_default
    }
    $("<div class='pokemon' id='" + pokemon.id + "'>" +
      upperCase_name + "<br><img src='" + pokemon.sprites.front_default + "'alt=''/><br>" + pokemon.id +
      "</div>").appendTo("#display_pokemon");
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="display_pokemon"></div>

  1. 如果在所有请求完成之前不显示任何内容很重要,只需在请求上使用 .always() 对已完成的请求保留一个计数器,并在每个请求后检查计数器是否等于 poke_name.length .如果是这样,那么您就知道每个口袋妖怪的请求都已完成(成功或失败),然后显示所有结果。

示例 2

get_sprites(["squirtle", "charmander", "not_a_pokemon", "bulbasaur", "onix", "mewtwo", "pikachu"])

function get_sprites(poke_names) {
  let poke_names_length = poke_names.length;
  let finished_requests = 0;
  let poke_array = [];

  for (let poke_name of poke_names) {
    $.getJSON("https://pokeapi.co/api/v2/pokemon/" + poke_name)
      .always(function() {
        finished_requests++
      })
      .done(addPokemon)
      .fail(function(err) {
        console.log(`error getting pokemon: ${poke_name} - ${err.status}`);
      })
  }

  function addPokemon(pokemon) {
    let upperCase_name = pokemon.name.charAt(0).toUpperCase() + pokemon.name.slice(1);

    let objPoke = {
      id: pokemon.id,
      name: upperCase_name,
      imgUrl: pokemon.sprites.front_default
    }

    poke_array.push(objPoke);

    if (poke_names_length === finished_requests) {
      displayPokemon();
    }
  }

  function displayPokemon() {
    let ordered_pokes = poke_array.sort(function(a, b) {
      return a.id - b.id;
    });

    for (let poke of ordered_pokes) {
      $("<div class='pokemon' id='" + poke.id + "'>" +
        poke.name + "<br><img src='" + poke.imgUrl + "'alt=''/><br>" + poke.id + "</div>").appendTo("#display_pokemon");
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="display_pokemon"></div>