MDN Web Docs: The map() method creates a new array with the results of calling a provided function on every element in the calling array.
Today I found myself in a situation where I had to use an asynchronous function inside of an Array.map. Needless to say, Array.map is a synchronous function. Therefore, I had a slight problem in my hands.
I came across this problem while refactoring my code to get rid of a nasty “for..of”. Basically, I had an Array of objects upon which I had to make several calculations. One of these calculations involved making a call to an API which, of course, is asynchronous. Before my refactoring, I had no problem with using async/await inside my for..of loop. However, after making the switch to Array.map, I realized it wouldn’t be as simple.
Here’s what I did:
As you can see, my getDistance function simulates a call to an API, and returns a Promise.
Note: The return value of async functions is always a Promise
This means that our Array.map function will return an Array of unresolved promises. Therefore, outside of the Array.map, we have to wait for all the promises to be resolved before we can make use of the resulting Array. This is why we use Promise.all().
Note: If you aren’t comfortable with async/await syntax, you can always resort to good ol’ “.then”
You can check out and play with my solution in the following CodePen:
Pretty simple, right? It took me a while to figure it out…
Which is why I decided to share my solution, in case someone else encounters this issue. I hope it helps! Thank you for reading, feel free to share or leave a comment :)
P.S. You can check out my Github and Twitter pages if you like...
Top comments (10)
Using
Promise.all(items.map(async (item) => asyncFunc(item))
looks pretty, but if you have thousands of items, it can eat a lot of your browser's resources managing all those promises. If resource consumption is a concern, there is nothing wrong withfor (const item of items) { await asyncFunc(item) }
.I tried this using HttpClient and a data service for my angular project, and it returns the mapped object, but the value of that http function is an observable object. I've no clue what I'm doing wrong to not get the right value.
The Angular HttpClient is designed to work with Observables (data streams), and this approach is Promise-based. You have two options:
Work with Observables, where you have to subscribe to the Observable object in order to access its data. You can find more information here
You can you use the toPromise() utility, which will transform the Observable you are receiving to a Promise, which you can then handle in the traditional way. More info about toPromise here
I hope this helps you out. Let me know :)
I use dev.to all the time, but this is the first time I've come here from googling a bug. Thanks for posting, and it fixed my issue!
Turns out you can't just do
Thank you, i was having a hard time to solve this
10/10
Thank you! This got me out of a jam today.
Thanks @nyagarcia 🤓
I'm sorry but this is quite hard to understand, especially without context on what you're actually doing or trying to do here.
Note: The return value of async functions is always a Promise
I guess this is something I hadn't fully grokked. You're not returning a Promise in the async function, yet it returns a Promise!