【问题标题】:Pushing result from promise.all into an array将 promise.all 的结果推送到数组中
【发布时间】:2020-09-05 23:33:03
【问题描述】:

正如标题所暗示的那样,我目前正在苦苦挣扎。我对正在发生的事情有所了解,尽管我无法让它 100% 以我想要的方式工作。

我的问题

在我的所有承诺都得到解决后,我想返回一个包含所有响应数据的数组。但是由于某种原因,当我在承诺之外返回口袋妖怪时,我得到的只是一个空数组。然而,在你看到的承诺中,我在第 5 次之后得到了我想要的包含 5 个对象的数组。有趣的部分是在我的主要功能 Pokegame 中,我还控制台登录 teamOne。但是,我得到一个空数组(“[]”),但与控制台日志“内部”具有相同的属性,但是我无法访问此数组中的键。我尝试了不同的方法,但由于某种原因,我无法从函数 getPokemons 返回“正常”数组。

代码

import React from "react";
import Pokedex from "./Pokedex";
import Pokecard from "./Pokecard";

var PokeAPI = "https://pokeapi.co/api/v2/pokemon/";

const getPokemonIDs = () => {
  var team = [];
  while (team.length < 5) {
    var randomPokemonID = Math.ceil(Math.random() * 807);
    team.push(randomPokemonID);
  }
  return team;
};

const getPokemons = () => {
  var pokemonIDs = getPokemonIDs();
  var pokemons = [];
  Promise.all(pokemonIDs).then(pokemonIDs => {
    for (let x in pokemonIDs) {
      fetch(PokeAPI + pokemonIDs[x])
        .then(response => response.json())
        .then(response => {
          pokemons.push(response);
          console.log("===inside===");
          console.log(pokemons);
        })
        .catch(error => {
          console.log(error);
        });
    }
  });
  console.log("==end==");
  console.log(pokemons.length);
  return pokemons;
};

const Pokegame = () => {
  const teamOne = getPokemons();
  console.log("==teamOne===")
  console.log(teamOne);

  return (
    <div>
      <Pokedex team={teamOne} />
    </div>
  );
};

export default Pokegame;

控制台输出

    ===inside===
    index.js:27 (5) [{…}, {…}, {…}, {…}, {…}]
    index.js:27 ==end==
    index.js:27 0

    ===teamOne===
    index.js:27 []
    0: {abilities: Array(2), base_experience: 63, forms: Array(1), game_indices: Array(0), height: 3, …}
    1: {abilities: Array(1), base_experience: 72, forms: Array(1), game_indices: Array(20), height: 6, …}
    2: {abilities: Array(3), base_experience: 175, forms: Array(1), game_indices: Array(9), height: 13, …}
    3: {abilities: Array(3), base_experience: 81, forms: Array(1), game_indices: Array(17), height: 5, …}
    4: {abilities: Array(2), base_experience: 238, forms: Array(1), game_indices: Array(4), height: 16, …}
    length: 5
    __proto__: Array(0)

    index.js:27 ===inside===
    index.js:27 [{…}]

    index.js:27 ===inside===
    index.js:27 (2) [{…}, {…}]

    index.js:27 ===inside===
    index.js:27 (3) [{…}, {…}, {…}]

    index.js:27 ===inside===
    index.js:27 (4) [{…}, {…}, {…}, {…}]

    index.js:27 ===inside===
    index.js:27 (5) [{…}, {…}, {…}, {…}, {…}]
    0: {abilities: Array(2), base_experience: 63, forms: Array(1), game_indices: Array(0), height: 3, …}
    1: {abilities: Array(1), base_experience: 72, forms: Array(1), game_indices: Array(20), height: 6, …}
    2: {abilities: Array(3), base_experience: 175, forms: Array(1), game_indices: Array(9), height: 13, …}
    3: {abilities: Array(3), base_experience: 81, forms: Array(1), game_indices: Array(17), height: 5, …}
    4: {abilities: Array(2), base_experience: 238, forms: Array(1), game_indices: Array(4), height: 16, …}
    length: 5
    __proto__: Array(0)

推测

所以我知道 promise 将被放入回调队列堆栈,这就是它第一次返回空数组的原因,但是我不明白为什么控制台日志 teamOne 甚至控制台日志口袋妖怪会用 like 记录一个空数组属性?

代码沙盒

【问题讨论】:

    标签: javascript arrays reactjs promise fetch


    【解决方案1】:

    除了拉达所说的Promise.all,AFAIK,如果你想异步更新你的模型,你需要使用useEffect也许useState

    import React from "react";
    import Pokedex from "./Pokedex";
    // import Pokecard from "./Pokecard";
    import { useEffect, useState } from "react";
    
    var PokeAPI = "https://pokeapi.co/api/v2/pokemon/";
    
    const getPokemonIDs = () => {
      var team = [];
      while (team.length < 5) {
        var randomPokemonID = Math.ceil(Math.random() * 807);
        team.push(randomPokemonID);
      }
      return team;
    };
    
    const getPokemons = () => {
      var pokemonIDs = getPokemonIDs();
      return Promise.all(
        pokemonIDs.map(pokemonId =>
          fetch(PokeAPI + pokemonId)
            .then(response => response.json())
            .then(response => {
              console.log("===inside===");
              return response;
            })
        )
      );
    };
    
    const Pokegame = () => {
      const [teamOne, setTeamOne] = useState([]);
    
      console.log(teamOne);
      useEffect(() => {
        getPokemons().then(team1 => {
          console.log(team1);
          setTeamOne(team1);
        });
      }, []);
      return (
        <div>
          <Pokedex team={teamOne} />
        </div>
      );
    };
    
    export default Pokegame;
    
    

    https://codesandbox.io/s/bold-sound-uoo6v?file=/src/components/Pokedex.js

    【讨论】:

      【解决方案2】:

      Promise.all() 的问题在于实际上没有任何承诺。 Promise.all() 接受一组承诺,而您正在传递一组 ID。 试试这个(删除日志):

      Promise.all(
        pokemonIDs.map(id => {
          return fetch(PokeAPI + id)
            .then(response => response.json())
            .then(result => {
              pokemons.push(result);
            });
        })
      ).then(() => {
        console.log("==end==");
        console.log(pokemons.length);
        console.log(pokemons);
      });
      

      这里的分叉沙箱:https://codesandbox.io/s/serverless-breeze-bozdm?file=/src/components/Pokegame.js(稍作编辑以与 React 集成)。

      就个人而言,我喜欢使用Promise.all() 来运行并行请求,但对于其他情况,我更喜欢async / await,因为它非常容易编写和阅读,无需过多思考。然后可以像这样重写原始示例(前提是父函数是异步的)

      await Promise.all(
        pokemonIDs.map(id => {
          return fetch(PokeAPI + id)
            .then(response => response.json())
            .then(result => {
              pokemons.push(result);
            });
        })
      );
      
      console.log("==end==");
      console.log(pokemons.length);
      console.log(pokemons);
      

      【讨论】:

        【解决方案3】:

        借助@láďa-durchánek 的回答,您可以进一步优化 Promise.all 调用:

        async function getThemAll(pokemonIDs) {
          const pokemons = await Promise.all(
            pokemonIDs.map(async (id) => {
              const response = await fetch(id);
              return response.json();
            })
          );
        
          console.log("==end==");
          console.log(pokemons.length);
          console.log(pokemons);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-03
          • 1970-01-01
          • 2011-10-08
          • 2017-10-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多