I am using pokeapi and I am creating a object inside a promise for every pokemon but I have to get the information that is in .species and is in another URL so I am calling another fetch but doesn´t give me the data.
const fetchPokemon = () => {
const promises = [];
for (let index = 1; index <= 150; index++) {
const url = `https://pokeapi.co/api/v2/pokemon/${index}`;
promises.push(fetch(url).then((res) => res.json()));
}
Promise.all(promises).then((results) => {
const pokemon = results.map((data) => ({
name: data.name,
egg_groups: getEgg(data)
}));
And the method that I am calling in egg_groups is like this:
return fetch(data.species.url).then((response) => response.json()).then(
(res)=> res.egg_groups.map((egg_group) => egg_group.name).join(" and "));
How I can get the "monster and plant" rather than the entire promise?
You can call the getEgg function for every result in the results array and then chain it with .then and resolve the resulting array using Promise.all.
const fetchPokemons = () => {
const promises = [];
for (let index = 1; index <= 2; index++) {
const url = `https://pokeapi.co/api/v2/pokemon/${index}`;
promises.push(fetch(url).then((res) => res.json()));
}
return Promise.all(promises).then((results) =>
Promise.all(results.map((data) =>
getEgg(data).then((egg) => ({
name: data.name,
egg_groups: egg,
}))
))
);
};
function getEgg(data) {
return fetch(data.species.url)
.then((response) => response.json())
.then((res) =>
res.egg_groups.map((egg_group) => egg_group.name).join(" and ")
);
}
fetchPokemons().then((pokemons) => pokemons.map(poke => {
document.body.innerHTML += `<p>${poke.name} - ${poke.egg_groups}</p>`
}));
You can also generate the data for each pokemon inside the getEgg function (renamed to getData), as shown below:
const fetchPokemons = () => {
const promises = [];
for (let index = 1; index <= 2; index++) {
const url = `https://pokeapi.co/api/v2/pokemon/${index}`;
promises.push(fetch(url).then((res) => res.json()));
}
return Promise.all(promises).then((results) =>
Promise.all(results.map(getData))
);
};
function getData(data) {
return fetch(data.species.url)
.then((response) => response.json())
.then((res) => ({
name: data.name,
egg_groups: res.egg_groups
.map((egg_group) => egg_group.name)
.join(" and "),
}));
}
fetchPokemons().then((pokemons) =>
pokemons.map((poke) => {
document.body.innerHTML += `<p>${poke.name} - ${poke.egg_groups}</p>`;
})
);
I would suggest using the async and await syntax, this allows you to structure asynchronous code in a more readable way.
We'd create a getPokemon() function that accepts an index argument. Once we retrieve the pokemon object using fetch() we can then get the eggs using the same function.
We can then return an object including the pokemon name, the egg_groups etc.
We can then also create a getPokemonArray() function that will fetch an array of pokemons, taking a start and end index as arguments:
async function getPokemon(index) {
const url = `https://pokeapi.co/api/v2/pokemon/${index}`;
const pokemon = await fetch(url).then((res) => res.json());
const eggs = await fetch(pokemon.species.url).then((response) => response.json());
const egg_groups = eggs.egg_groups.map((egg_group) => egg_group.name).join(" and ");
return { index, name: pokemon.name, egg_groups };
}
async function getPokemonArray(startIndex, endIndex) {
let promises = [];
for (let index = startIndex; index <= endIndex; index++) {
promises.push(getPokemon(index));
}
let pokemonArray = await Promise.all(promises);
console.log('Pokemon array:', pokemonArray);
return pokemonArray;
}
getPokemonArray(1,3);
getPokemonArray(40,42);
.as-console-wrapper { max-height: 100% !important; }
You should insert the async keyword for the map function to be async to use await there. Since you need to "await" for the promise to resolve to get the result.
Promise.all(promises).then((results) => {
const pokemon = results.map(async (data) => ({
name: data.name,
egg_groups: await getEgg(data)
}));
return pokemon;
});