Reputation: 2807
This code snippet is taken from google developers:
// map some URLs to json-promises
const jsonPromises = urls.map(async url => {
const response = await fetch(url);
return response.json();
});
I understand that at the end jsonPromises
is going to be an array of Promises. However, i'm not completely sure how that happens.
According to my understanding, when execution gets to this line const response = await fetch(url);
it moves it from call stack to Web Api, does the same to return response.json();
and moves to the next url
from urls
. Is it correct ? I understand how event loop works when it comes to simple setTimeout
, but this example confuses me a lot.
Upvotes: 0
Views: 470
Reputation: 138257
Here's what happens:
1) The .map
function runs, and executes the callback for each element (the async function). The function calls fetch
, which starts some under the hood magic inside the engine. fetch
returns a Promise. The await
gets reached, which halts the functions execution. The call to the function done by .map
evaluates to a promise. .map
collects all those promises and stores them in an array and returns the array.
2) Somewhen, one of the fetches running under the hood has etablished a connection, and calls back into JS and resolves the fetch
promise. That causes the async function
call to go on. res.json()
gets called, which causes the engine to collect all the packets from the connection and parse it as JSON under the hood. That again returns a Promise, which gets await
ed, which causes the execution to stop again.
3) Somewhen, one of the connections end, and the whole response is available as JSON. The promise resolves, the async function
call continues execution, return
s, which causes the promise (the one in the array) to be resolved.
Upvotes: 1
Reputation: 650
Since async functions return a promise, think of the example as any other promise-returning function:
// map happens synchronously and doesn't wait for anything
const map = (arr, cb) => {
const mapped = [];
for (const [i, element] of arr.entries()) {
mapped.push(cb(element))
}
return mapped;
}
// just return a promise that resolves in 5 seconds with the uppercased string
const promiseFn = url => {
return new Promise(resolve => setTimeout(() => resolve(url.toUpperCase()), 5000))
}
const promiseArray = map(['url', 'url', 'url'], promiseFn)
All the promises returned by the async callback are pushed synchronously. Their states are modified asynchronously.
If on the other hand you're looking for the difference between setTimeout and a Promise vis-a-vis the event loop, check the accepted answer here: What is the relationship between event loop and Promise
Upvotes: 1