Introduction
This post will discuss using JavaScript's map method when dealing with async/await and promises. I'll be using a real-world example from my most recent project, viewable here.
Async/Await
To start, I first had to fetch data from The Covid Tracking Project's API, so I did it using async/await
, like so:
async function fetchTestingData() {
const response = await axios.get(
"https://covidtracking.com/api/v1/states/current.json"
);
return const data = response;
}
The await
keyword in the snippet above does what it describes: it forces the rest of the code to literally await the promise until it resolves. Async
makes it so that the function always returns a promise.
Without an async/await, the data variable may come back undefined, since it may not fetch the response from the API before the return executes.
Combining the Map Method with Async/Await
The next step is to iterate over each state and attach coordinates, like so:
const addCoordinates = data.map(async state => {
const coordinates = await axios.get(`https://exampleAPI.com/geocode/json?address=${state.stateName}`);
state.coordinates = coordinates;
return state
});
JavaScript's map method uses a callback to apply the function over each element of the array, which is fine. But recall that async functions always return a promise. As a result, you are returning an array of promises.
To summarize: the map method is a synchronous operation, but we are trying to do something asynchronous here, which combined with async/await
leads to an array of promises instead of values.
Using Promise.all with an Asynchronous Map Method
The solution here is to use Promise.all, like so:
const addCoordinates = data.map(async state => {
const coordinates = await axios.get(`https://exampleAPI.com/geocode/json?address=${state.stateName}`);
state.coordinates = coordinates;
return state
});
const allStatesWithCoordinates = Promise.all(addCoordinates);
Promise.all is designed to take an array of promises as input and returns only one promise after all input promises have resolved, meaning the output will be one of values.
Top comments (2)
Great article!
Can you please explain why does
addCoordinates
comes to be an array of promises, but not an array of objects/arrays?When we do this for a single request, like in the first snippet it does return only the required data (not like any promise)
nice article.
I see the same problem than @saiyerniakhil .
You need to put your map code inside the promise.all. If you don't do this, you will execute the promises a line before.