JavaScript Fetch & Push Array 返回 "undefined"



我正在用普通的javascript编写一个应用程序。我遇到了一个问题,当将 150 个对象放入数组中时,数组中的某些对象是未定义的。 当我控制台时.log对象在被推入数组之前,它们很好,所有 150 个对象都显示出来。 但是,当我将它们推送到数组时,有些是未定义的,有些确实被成功推送。 我的理解是,这可能是序列计时问题,对于某些对象,它们可能尚未完全获取,但推送到数组已经发生。 有没有办法确保它们被排序,以便只有在完全成功获取对象后才会推送数组? 感谢您的帮助。

const fetchPokemon = function () {
const pokemons = [];
for ( let i=1; i <= 150; i++) {
const url = `https://pokeapi.co/api/v2/pokemon/${i}`;
fetch(url).then( res => { return res.json(); })
.then( data => {
const pokemon = {
name: data.name,
id: data.id          
};
pokemons.push(pokemon);
console.log(pokemon);
console.log(pokemons[i]);
});
}
};
fetchPokemon();

输出 - 根据未定义的数组元素的不同页面重新加载而变化

app.js:17 undefined
app.js:16 {name: "dragonite", id: 149}
app.js:17 undefined
app.js:16 {name: "mewtwo", id: 150}
app.js:17 undefined
app.js:16 {name: "kingler", id: 99}
app.js:17 {name: "electrode", id: 101}
app.js:16 {name: "aerodactyl", id: 142}
app.js:17 {name: "zapdos", id: 145}
app.js:16 {name: "dratini", id: 147}
app.js:17 {name: "kingler", id: 99}

您的问题是,虽然每个请求fetch都是异步的,但您会在所有 150 个请求完成之前返回。在下面的 for 循环中,不是链接到请求并立即推送,而是将 promise 推送到requests数组中。然后,在循环之后,返回一个 Promise,一旦请求了所有 150 个承诺并将其推送到pokemons数组中,它就会解析。

const fetchPokemon = function() {
const pokemons = [];
const requests = [];
for (let i = 1; i <= 150; i++) {
const url = `https://pokeapi.co/api/v2/pokemon/${i}`;
const prom = fetch(url).then((r) => r.json());
requests.push(prom);
}
return new Promise((resolve) => {
Promise.all(requests)
.then((proms) =>
proms.forEach((p) => pokemons.push({
name: p.name,
id: p.id
}))
)
.then(() => resolve(pokemons));
});
};
fetchPokemon().then(console.log);

在这里发布这个,作为一个更简单、更简洁和最佳的例子,使用 async/await。
并行提取,具有迭代第一个顺序就绪获取响应的功能。 即:如果前 25 个获取完成,它将按顺序迭代前 25 个,而不等待后 125 个。

const fetchPokemon = async function() {
const pokemons = [];
for (let i = 1; i <= 150; i++) {
const url = `https://pokeapi.co/api/v2/pokemon/${i}`;
const data = fetch(url).then(res => res.json())
.then( ({name, id}) => ({name, id}) );
pokemons.push(data);
}
for await (const pokemon of pokemons) {
console.log(pokemon);
}
// or if you need to use the index:
for (let i = 0; i < pokemons.length; i++) {
console.log(await pokemon[i]);
}
};
fetchPokemon();

最新更新