I have a block of code here. It fetches 4 API calls to pokiapi, converts the response to JSON, then converts that response to only show the name, and so when Promise.all()
resolves it should return an array of 4 Pokemon name.
handleClick(event) {
event.preventDefault()
const randNum1 = Math.floor(Math.random() * this.totalPokemon)
const randNum2 = Math.floor(Math.random() * this.totalPokemon)
const randNum3 = Math.floor(Math.random() * this.totalPokemon)
const randNum4 = Math.floor(Math.random() * this.totalPokemon)
Promise.all([
fetch('https://pokeapi.co/api/v2/pokemon/' + randNum1),
fetch('https://pokeapi.co/api/v2/pokemon/' + randNum2),
fetch('https://pokeapi.co/api/v2/pokemon/' + randNum3),
fetch('https://pokeapi.co/api/v2/pokemon/' + randNum4),
])
.then(responses => Promise.all(responses.map(r => r.json())))
.then(responses => Promise.all(responses.map(r => r.name)))
.then(responses => console.log(responses))
}
The last line of code is to console log the response and I get what I expected, which is an array of Pokemon name. An example might be ["mewtwo", "jynx", "ponyta", "geodude"].
BUT, when I include a new line just before console log to shuffle the previous array using fisherYatesShuffle()
, the console log now returns undefined:
handleClick(event) {
event.preventDefault()
const randNum1 = Math.floor(Math.random() * this.totalPokemon)
const randNum2 = Math.floor(Math.random() * this.totalPokemon)
const randNum3 = Math.floor(Math.random() * this.totalPokemon)
const randNum4 = Math.floor(Math.random() * this.totalPokemon)
Promise.all([
fetch('https://pokeapi.co/api/v2/pokemon/' + randNum1),
fetch('https://pokeapi.co/api/v2/pokemon/' + randNum2),
fetch('https://pokeapi.co/api/v2/pokemon/' + randNum3),
fetch('https://pokeapi.co/api/v2/pokemon/' + randNum4),
])
.then(responses => Promise.all(responses.map(r => r.json())))
.then(responses => Promise.all(responses.map(r => r.name)))
.then(responses => this.fisherYatesShuffle(responses))
.then(responses => console.log(responses))
}
I don't think the fisherYatesShuffle()
method is wrong because I've tried it on other arrays I make for testing purposes and it was perfectly fine. Just in case, here is the implementation of the fisherYatesShuffle().
//Takes in an array and returns a shuffled array
fisherYatesShuffle(guesses) {
for (let i = guesses.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * i)
const temp = guesses[i]
guesses[i] = guesses[j]
guesses[j] = temp
}
}
I suspect that this is a problem with the way the responses are returned, but what can it be?
Edit: Ah apparently the problem WAS my fisherYatesShuffle()
method. I originally tested it with some random arrays I made but my testing must've been bad because it didn't catch my error.
The problem is that fisherYatesShuffle
doesn't return anything. (There is no return
statement in it.) Instead it simply re-orders the array that's passed to it. This means that .then(responses => this.fisherYatesShuffle(responses))
puts undefined
as the intermediate result of the Promise chain, so that's what you observe in the console.log
.
There are 2 potential fixes, depending on which part you want to change.
Option 1 - make fisherYatesShuffle
return its contents:
fisherYatesShuffle(guesses) {
for (let i = guesses.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * i)
const temp = guesses[i]
guesses[i] = guesses[j]
guesses[j] = temp
}
return guesses; // add this line
}
Option 2 - change the promise chain to explicitly return the shuffled array:
.then(responses => {
this.fisherYatesShuffle(responses);
return responses;
})
.then(responses => console.log(responses))