Noob
Noob

Reputation: 2807

.map async callback and event loop

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

Answers (2)

Jonas Wilms
Jonas Wilms

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 awaited, 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, returns, which causes the promise (the one in the array) to be resolved.

Upvotes: 1

adamz4008
adamz4008

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

Related Questions