Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
189
rated 0 times [  195] [ 6]  / answers: 1 / hits: 5497  / 4 Years ago, thu, april 23, 2020, 12:00:00

If I have an array of elements and I want to do parallel operations on them.


I would use promise.all().



I knew promise.all() accepts array of promises. Correct me if I am wrong, I don't think so.


Here, it clearly says.




The Promise.all() method returns a single Promise that fulfills when all of the promises passed as an iterable have been fulfilled or when the iterable contains no promises or when the iterable contains promises that have been fulfilled and non-promises that have been returned. It rejects with the reason of the first promise that rejects, or with the error caught by the first argument if that argument has caught an error inside it using try/catch/throw blocks.




So, yes we can pass simple functions to promise.all(), and it resolves if they return and rejects if they throw an error.


Now look at the below code.




const promises = todayAssignedJobs.map(async todayAssigned => {
const [leaderboard, created] = await Leaderboard.findOrCreate({...});

if (!created) {
const rating = (todayAssigned.rating + leaderboard.rating * leaderboard.jobs_completed) / (leaderboard.jobs_completed + 1);
const commission = todayAssigned.commission + leaderboard.commission;
const jobsCompleted = leaderboard.jobs_completed + 1;

await Leaderboard.update({
rating,
commission,
jobs_completed: jobsCompleted,
updated_by: 'system',
}, {
where: {
id: leaderboard.id,
},
});
}

await AssignedJob.update({
is_leaderboard_generated: true,
}, {
where: {
id: todayAssigned.id,
},
});
});

await Promise.all(promises);


Here, I have a doubt.


We are iterating on each element of the array and doing operation on them asyncrhonously. They don't return anything explicitly.


So, I think map is doing parallel operations here too.


Why shuold then use promise.all() here?


More From » node.js

 Answers
4

.map() is not promise-aware. So, when you pass it an async callback like you are, it does not pay any attention to that returned promise. So, it just runs the loop one after another, not waiting for any of the returning promises. Thus, all the asynchronous operations started in the .map() loop will be in-flight at the same time.



If that's what you want and you want to collect all the returned promises so you can later see when they are all done with Promise.all(), then this pattern works well:



Promise.all(someArray.map(callbackThatReturnsAPromiseHere))


And, this is a common design pattern for it. In fact, the Bluebird promise library has a special function that combined these two called Promise.map(). It also offered another nice feature that let you control how many concurrent async operations could run at once (because it's map() operation is promise-aware).



It sounds like you're trying to figure out if you should only use .map() and not use Promise.all(). If you do that, you will run your asynchronous operations in parallel, but you will not have any idea when they are all done or any ability to collect all the results. You would use Promise.all() on the array of returned promises to know when they are all done and/or to collect their resolved results.



FYI, .map() is JUST a plain loop. It doesn't have any special asynchronous features or any special run-in-parallel features. You can do the same thing with a for loop if you want. It does NOT pause for your async callback to wait for it to be done so a side effect of running it is that you launch a bunch of parallel asynchronous operations.


[#4061] Monday, April 20, 2020, 4 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
daja

Total Points: 407
Total Questions: 103
Total Answers: 103

Location: Ghana
Member since Sun, Mar 27, 2022
2 Years ago
daja questions
Tue, Dec 21, 21, 00:00, 3 Years ago
Fri, Sep 6, 19, 00:00, 5 Years ago
Tue, Jul 23, 19, 00:00, 5 Years ago
Sat, Apr 27, 19, 00:00, 5 Years ago
;