In a project, I had a situation to perform an asynchronous task inside a loop. I majorly used the map method to do looping tasks.
myIterable.map((item) => {
// task 1 - normal
// task 2 - async
})
But the map method does not natively support async tasks, when something is made asynchronous inside the map method it returns some 'pending promises'.
[ Promise{ <pending> },... ]
To make the map method asynchronous I wrapped it with the concept of promises.
The logic is split into three code blocks.
In the first block, we have a function named myAsyncIteration
which returns a promise. Inside the promise we perform the asynchronous task and we can confirm the completion by resolving the promise by passing someData
const myAsyncIteration = (item) =>
new Promise(async (resolve, reject) => {
// task 1 - normal
// task 2 - async
return resolve(someData)
})
In the second block, inside myAsyncLoop
we map over every instance in myIterable
to myAsyncIteration
that returns a promise.
If there are 'n' instances inside myIterable
then 'n' promises will be returned. This is wrapped with Promise.all
which will ensure all the promises are executed and will contain the data which was resolved from the promises.
const myAsyncLoop = async () => {
return Promise.all(myIterable.map(async (item) =>
myAsyncIteration(item)
))
}
In the third block, we call myAsyncLoop
which returns an array of data sent after resolving each promise. It means 'n' number of someData
contributes to arrayOfSomeData
.
myAsyncLoop().then((arrayOfSomeData) => {
console.log(arrayOfSomeData)
// perform the other work
})
In this way, I performed async tasks inside the map method. This is my first blog post, please share your thoughts and if there are any better methods please mention them also.
Thank you.
Top comments (9)
Perhaps I'm misunderstanding something.
An async task should already be or return a promise (thenable) so wrapping it is unnecessary.
It's synchronous tasks that need to be wrapped in a promise with an executor.
If you want all to be settled perhaps you should be using
Promise.allSettled()
instead as thePromise.all()
promise will reject on the first rejection.It returns a promise that will resolve to the array of data (as your later code demonstrates) unless one of them rejects.
OK, that's the happy path.
How are you dealing with potential rejection?
Edge case: Be careful about promises the may never resolve: e.g. browser autoplay policies can lead to promises from
play()
/resume()
that never resolve.Thank you for your detailed valuable feedback. It gave me more insights into issues that would cause due to the improper handling of promises. I will go through the points you mentioned and correct my code. I want to clarify that I wrote the
// task 2 - async
comment as an abstraction for an awaiting database record existing check operation. I wish you a good day.Using map for async tasks here I'm fetching 10 todos from json place holder.
Thank you for the crisp code demonstration. It gave me insights on using inline async function blocks. I want to clarify that I wrote the
task 2 - async
comment as an abstraction for an awaiting database record existing check operation. I wish you a good day.Thank you for your valuable feedback. I will go through the points you mentioned and correct my code. I want to clarify that I wrote the 'task 2 - async' comment as an abstraction for an awaiting database record existing check operation. I wish you a good day.
I want to clarify that I wrote the
// task 2 - async
comment as an abstraction for an awaiting database record existing check operation.No need to declare async function if you never await anything
Thank you for your valuable feedback. I want to clarify that I wrote the
// task 2 - async
comment as an abstraction for an awaiting database record existing check operation. I wish you a good day.I mean here :
The first async is useless because you return a promise and on the second I think you should await myAsyncIteration(item).