Parallel operations with Promise.all?
I'd suggest to use it like this:
const [
res1,
res2
] = await Promise.all([
asyncCall1(),
asyncCall1(),
]);
A non-Async body is executed serially The moment you reach a Async call within your body (Ex. Hit a URL), Other Promises in the array will start executing.
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!")
})
To build on what Johannes Merz started, I propose this code to clarify that things are happening in parallel.
JS is single-threaded, but Node.js has plenty of tools for launching additional threads explicitly and implicitly. Promises expose more functionality we often need without having to launch new threads or processes explicitly. Promise.all() is such an example, but you need to be comfortable with Promises to use it without creating serious headaches for yourself, such as Promise Scope memory leaks.
function randomResolve(name,t) {
return new Promise(resolve => setTimeout(() => {
console.log({ name, t });
resolve({ name, t });
}, t));
}
(() => {
// Get epoch time before starting so we can confirm the execution time reflects our slowest timeout
let start = new Date().valueOf();
Promise.all([
randomResolve(1, 1000 * Math.random()),
randomResolve(2, 1000 * Math.random()),
randomResolve(3, 1000 * Math.random()),
randomResolve(4, 1000 * Math.random()),
])
.then(function( res ){
console.info( res );
console.log("All Done!", parseInt(new Date().valueOf() - start) );
})
})();
This pattern takes an array of inputs and uses array.map() to get back an array of launched promises which will be parallel processed as above. Notice there is NO use of async/await here.
function randomResolve(name,t) {
return new Promise(resolve => setTimeout(() => {
console.log({ name, t });
resolve({ name, t });
}, t));
}
(() => {
// Get epoch time before starting so we can confirm the execution time reflects our slowest timeout
let start = new Date().valueOf(),
vals = [
[1, 1000 * Math.random()],
[2, 1000 * Math.random()],
[3, 1000 * Math.random()],
[4, 1000 * Math.random()]
];
Promise.all( vals.map( v => { return randomResolve(v[0], v[1] ); } ) )
.then(function( res ){
console.info( res );
console.log("All Done!", parseInt(new Date().valueOf() - start) );
})
})();
This version does implement async/await.
function randomResolve(name,t) {
return new Promise(resolve => setTimeout(() => {
console.log({ name, t });
resolve({ name, t });
}, t));
}
(async () => {
// Get epoch time before starting so we can confirm the execution time reflects our slowest timeout
let start = new Date().valueOf(),
vals = [
[1, 1000 * Math.random()],
[2, 1000 * Math.random()],
[3, 1000 * Math.random()],
[4, 1000 * Math.random()]
];
let res = await Promise.all( vals.map( async v => { return await randomResolve( v[0], v[1] ); } ) );
// await the Promise.aall() call instead of using .then() afterwards with another closure then
// forEach v in vals, start and await a Promise from randomResolve() then return the result to map
console.info( res );
console.log("All Done!", parseInt(new Date().valueOf() - start) );
})();