I have this piece of code:
const Axios = require('axios');
const baseURL = 'https://jsonplaceholder.typicode.com';
async function main() {
const posts = await Axios(`${baseURL}/posts`);
const users = await Promise.all(posts.data.map( async (post, index) => {
let d = await Axios(`${baseURL}/users/${post.userId}`);
return d.data.name;
}))
users.map( (user, index) => {
console.log( `${index}. ${user}` );
});
}
And outputs the result in order:
1. Patricia
2. Glenna
3. Nicholas
4. Kurtis
5. Chelsey
Everything Ok, but ... If I do:
async function main() {
const posts = await Axios(`${baseURL}/posts`);
await Promise.all(posts.data.map( async (post, index) => {
let d = await Axios(`${baseURL}/users/${post.userId}`);
console.log( `${index}. ${d.data.name}` );
}))
}
the console.log
inside map
prints the list unordered ...
2. Glenna
4. Kurtis
5. Chelsey
1. Patricia
3. Nicholas
My question is:
Why in the first code map
returns the list ordered, and in the second one the console.log
inside map
, prints the list unordered ?
Promise.all
is designed to keep the order of the results of the promises that were passed to it, independent of the order those promises actually resolved. So when Promise.all
resolves, it means all individual promises resolved, and then Promise.all
resolves to the array of resolutions in the same order as the corresponding promises have in the array.
If however you output the values as soon as their promises resolve, then the above has of course no effect on your output -- it will now be ordered by the order in which the individual promises resolve.
Let's say there are three promises p1
,p2
, p3
that resolve to 1, 2 and 3. But the second promise will resolve sooner than the other two.
Promise.all
is called with [p1, p2, p3]
. It returns a new promise that will eventually resolve to [1, 2, 3]
. During the time that not all promises are resolved, you could imagine that an internal array evolves as follows:
p2
resolves. Promise.all
internally stores [undefined, 2, undefined]
p1
resolves. Promise.all
internally stores [1, 2, undefined]
p3
resolves. Promise.all
also resolves with value [1, 2, 3]
Here you can see that the first code would output 2, 1, 3 while the second would output 1, 2, 3