You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌套Fetch获取Pokemon数据无法存入数组的问题排查与解决

为什么嵌套Fetch获取的Pokemon对象无法存入数组?怎么解决?

问题原因

核心问题是异步操作的执行顺序:
你调用getPokemon()后立刻执行console.log(pokemonsArray.length),但fetch是异步网络请求,所有的请求发送、数据接收、数组push操作都还没完成,此时数组自然是空的,长度为0。

解决方案

下面提供两种清晰的实现方案,解决异步同步问题的同时优化代码结构:

方案1:使用async/await + Promise.all(推荐,代码更易读)

const cards = document.querySelector(".cards");
const error = document.querySelector(".err");
const search = document.querySelector("#search");
let url = "https://pokeapi.co/api/v2/pokemon?limit=100&offset=0";

let pokemonsArray = [];

const createPokemons = (pokemon) => {
  pokemonsArray.push(pokemon);
};

// 改为async函数,用await处理异步流程
const getPokemon = async () => {
  try {
    // 第一步:获取Pokemon列表
    const res = await fetch(url);
    if (!res.ok) throw new Error("data could not be fetched");
    const data = await res.json();

    // 第二步:并行发起所有详情请求,提升效率
    const pokemonDetailPromises = data.results.map(async (item) => {
      const result = await fetch(item.url);
      if (!result.ok) throw new Error("could not fetch new url");
      return result.json();
    });
    const pokemonDetails = await Promise.all(pokemonDetailPromises);

    // 第三步:处理所有详情数据,存入数组
    pokemonDetails.forEach(detail => {
      const pokemon = {
        name: detail.species.name,
        image: detail.sprites.other.home.front_default,
      };
      createPokemons(pokemon);
    });

    // 此时数组已填充完成,可正常操作
    console.log(pokemonsArray.length); // 输出100
  } catch (err) {
    console.log(err);
  }
};

getPokemon();
// 不要在getPokemon调用后直接log数组,因为异步操作还没完成

方案2:基于.then的改进写法(不使用async/await)

const cards = document.querySelector(".cards");
const error = document.querySelector(".err");
const search = document.querySelector("#search");
let url = "https://pokeapi.co/api/v2/pokemon?limit=100&offset=0";

let pokemonsArray = [];

const createPokemons = (pokemon) => {
  pokemonsArray.push(pokemon);
};

const getPokemon = () => {
  fetch(url)
    .then((res) => {
      if (!res.ok) throw new Error("data could not be fetched");
      return res.json();
    })
    .then((data) => {
      // 将每个详情请求包装为Promise,收集到数组中
      const pokemonPromises = data.results.map((item) => {
        return fetch(item.url)
          .then((result) => {
            if (!result.ok) throw new Error("could not fetch new url");
            return result.json();
          })
          .then(detail => ({
            name: detail.species.name,
            image: detail.sprites.other.home.front_default,
          }));
      });
      // 等待所有Promise完成后返回结果
      return Promise.all(pokemonPromises);
    })
    .then((pokemonList) => {
      // 批量存入数组
      pokemonsArray.push(...pokemonList);
      console.log(pokemonsArray.length); // 输出100
    })
    .catch((err) => {
      console.log(err);
    });
};

getPokemon();

关键注意点

  1. 异步结果的访问时机:必须在所有异步操作完成后才能访问填充后的数组,比如在await Promise.all之后或.then的回调中。
  2. Promise.all的作用:并行处理多个异步请求,比逐个嵌套fetch效率更高,同时避免“回调地狱”。
  3. 外部使用数组的方式:如果需要在getPokemon函数外部使用数组,可以让函数返回Promise,外部通过await或.then获取结果。

内容的提问来源于stack exchange,提问作者Hasan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 23:45:41