嵌套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();
关键注意点
- 异步结果的访问时机:必须在所有异步操作完成后才能访问填充后的数组,比如在
await Promise.all之后或.then的回调中。 - Promise.all的作用:并行处理多个异步请求,比逐个嵌套
fetch效率更高,同时避免“回调地狱”。 - 外部使用数组的方式:如果需要在
getPokemon函数外部使用数组,可以让函数返回Promise,外部通过await或.then获取结果。
内容的提问来源于stack exchange,提问作者Hasan
相关产品推荐
相关产品推荐

