Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Promise.all not working with an array of async functions

Consider the following code which print messages to console after I/O operations complete, in theory.

const foo = (num) => new Promise(resolve => setTimeout(resolve, num * 1000)); // An async I/O function in actual code
array = [[1, 2, 3], [1, 2, 3] , [1, 2, 3]];

const promiseArray = array.map(arr => {
  arr.map(num => {
    return (async () => {
      await foo(num);
      console.log(num);
    });
  });
}).flat();

await Promise.all(promiseArray);

I don't know why but it doesn't work. Nothing was printed to the console.


However it would work if I wrap the async function within a Promise constructor

const foo = (num) => new Promise(resolve => setTimeout(resolve, num * 1000)); // An async I/O function in actual code
array = [[1, 2, 3], [1, 2, 3] , [1, 2, 3]];

const promiseArray = array.map(arr => {
  arr.map(num => {
    return new Promise(async () => {
      await foo(num);
      console.log(num);
    });
  });
}).flat();

await Promise.all(promiseArray);

How should I rewrite the code to get rid of the Promise constructor?

like image 397
Max Avatar asked Jul 26 '20 16:07

Max


People also ask

How do you resolve all promises in a promise array?

1. Wait for all promises to complete with Promise.all Promise.all accepts an array of promises and returns a new promise that resolves only when all of the promises in the array have been resolved. The promise resolves to an array of all the values that the each of the promise returns.

What is async-await in promise?

Example: Following is the pseudo code (not runnable one) which will help you to understand more about Promise.all (). Async-await are the two keywords which we use to illustrate a particular function or method as asynchronous data acceptor.

Should you pass async functions to foreach in JavaScript?

If we pass async functions to forEach, we have no way of retrieving the returned promise to do anything useful with it. Unless you want to fire the async function and forget about it, passing async functions to forEach is never something you want to do. There you go! That is all 5 cheatsheets on what to do and not to do with an array of Promises.

How to execute promise all () method for several promises in JavaScript?

Syntax: Following is the syntax which we could use in order to execute Promise.all () method for several promises: Promise.all ( [ first_promise , second_promise, .......])


Video Answer


3 Answers

Promise.all takes an array of promises as its argument, not an array of async functions. Also you were missing a return statement. You should write

const promiseArray = array.flatMap(arr => {
  return arr.map(async num => {
    await foo(num);
    console.log(num);
  });
});

await Promise.all(promiseArray);

or

const promiseArray = array.map(async arr => {
  await Promise.all(arr.map(async num => {
    await foo(num);
    console.log(num);
  }));
});

await Promise.all(promiseArray);
like image 60
Bergi Avatar answered Oct 19 '22 21:10

Bergi


Its normal Promise.all take an array of Promises, async function are of type function, but returns a Promise once invoked if no explicite return it will return a resolved promise with undefined value.

async function myAsyncFunction(){
  return 1; 
}

console.log(typeof myAsyncFunction)
console.log(typeof myAsyncFunction())
console.log(myAsyncFunction() instanceof Promise)
like image 20
Mehdi Belbal Avatar answered Oct 19 '22 20:10

Mehdi Belbal


You are returning a function from map callback, not a promise. instead return foo(num). then after flattening you have an array of promises.

const foo = (num) => new Promise(resolve => setTimeout(resolve, num * 1000)); // An async I/O function in actual code
array = [[1, 2, 3], [1, 2, 3] , [1, 2, 3]];

const promiseArray = array.map(arr => {
  return arr.map(foo); // its equal arr.map(num => foo(num));
}).flat();

const results = await Promise.all(promiseArray);
results.forEach(item => console.log(item));
like image 1
Kavian Rabbani Avatar answered Oct 19 '22 21:10

Kavian Rabbani