Is Node.js native Promise.all processing in parallel or sequentially?
Is
Promise.all(iterable)
executing all promises?
No, promises cannot "be executed". They start their task when they are being created - they represent the results only - and you are executing everything in parallel even before passing them to Promise.all
.
Promise.all
does only await multiple promises. It doesn't care in what order they resolve, or whether the computations are running in parallel.
is there a convenient way to run an iterable sequencially?
If you already have your promises, you can't do much but Promise.all([p1, p2, p3, …])
(which does not have a notion of sequence). But if you do have an iterable of asynchronous functions, you can indeed run them sequentially. Basically you need to get from
[fn1, fn2, fn3, …]
to
fn1().then(fn2).then(fn3).then(…)
and the solution to do that is using Array::reduce
:
iterable.reduce((p, fn) => p.then(fn), Promise.resolve())
Does Promise.all() run in sequential or parallel?
Javascript is a single threaded application. However, asynchronous calls allow you to not be blocked by that call. This is particularly useful when making REST API calls. For example your promise1()
can make a REST API call and before it waits for the results, another REST API call can be made from promise2()
. This pseudo-parallelism is thus achieved by not waiting on API servers to do the tasks and fire multiple such calls to either same or different API endpoints in parallel. This allows your code to continue executing that parts that are not dependent on resolution of the promises.
So yes, promise1()
, promise2()
and promise3()
can be said to be running in parallel in that respect. And there is a chance that promise2()
gets resolved before promise1()
and so on. The function Promise.all()
waits for all the promises provided to it to fulfill or at least one of them to fail.
Learn more about Javascript event loops in this video by Jake Archibald.
Promise.all() and parallel promises are they differ in node
The second approach will be more performant.
In the first example assume that each request takes 1 second to return, so you will take at least 3+ seconds to return your results as you wait for the result of one request before making the next.
In the second approach you make all the requests at once, and then wait for the IO callback. Once all the requests are handled the Promise.all()
will resolve. If each request takes ~1 sec but is made in parallel your response will be about 1 second as well.
I would use syntax like the following however to maintain readability as you seem to be using async/await
and don't need to have a reference to the promises
.
try {
const [addresses, emails, phones] = await Promise.all([
searchArray.includes('address')
? axios('./getAddress') : Promise.resolve({}),
searchArray.includes('email')
? axios('./email') : Promise.resolve({}),
searchArray.includes('phone')
? axios('./phone') : Promise.resolve({}),
]);
return res.status(200).json({
addresses: addresses.data,
emails: emails.data,
phoneNumbers: phones.data,
});
} catch (err) {
return res.status(constants.HTTP_SERVER_ERROR).json(err);
}
Sequential execution of Promise.all
the Promises unfortunatelly does not allow any control of their flow. It means -> once you create new Promise, it will be doing its asynchronous parts as they like.
The Promise.all
does not change it, its only purpose is that it checks all promises that you put into it and it is resolved once all of them are finished (or one of them fail).
To be able to create and control asynchronous flow, the easiest way is to wrap the creation of Promise into function and create some kind of factory method. Then instead of creating all promises upfront, you just create only one promise when you need it, wait until it is resolved and after it continue in same behaviour.
async function doAllSequentually(fnPromiseArr) { for (let i=0; i < fnPromiseArr.length; i++) { const val = await fnPromiseArr[i](); console.log(val); }}
function createFnPromise(val) { return () => new Promise(resolve => resolve(val));}
const arr = [];for (let j=0; j < 10; j++) { arr.push(createFnPromise(Math.random()));}
doAllSequentually(arr).then(() => console.log('finished'));
Parallel operations with Promise.all?
It's because your Promises are blocking and synchronous! Try something with a timeout instead of a synchronous loop:
function randomResolve(name) {
return new Promise(resolve => setTimeout(() => {
console.log(name);
resolve();
}, 100 * Math.random()));
}
Promise.all([
randomResolve(1),
randomResolve(2),
randomResolve(3),
randomResolve(4),
])
.then(function(){
console.log("All Done!")
})
Related Topics
Check If an Array Is Empty or Exists
How to Convert the "Arguments" Object to an Array in JavaScript
Get Local Ip Address in Node.Js
How to Add an Object to an Array
How to Call 3 Functions in Order to Execute Them One After the Other
What's the Difference Between Window.Location= and Window.Location.Replace()
How to Get Visitor's Location (I.E. Country) Using Geolocation
How to Add Conditional Attribute in Angular 2
(![]+[])[+[]]... Explain Why This Works
How to Execute Shell Command in JavaScript
How to Calculate Md5 Hash of a File Using JavaScript
Detecting When a Div's Height Changes Using Jquery
Why 'Null >= 0 && Null <= 0' But Not 'Null == 0'
Angularjs Changes Urls to "Unsafe:" in Extension Page
Getting Scroll Bar Width Using JavaScript
Convert Hh:Mm:Ss String to Seconds Only in JavaScript
How to Check If an Element Is Really Visible with JavaScript
What Is the Cleanest Way to Get the Progress of Jquery Ajax Request