How to use Promise.all() when I'd like to pass

2019-07-25 08:05发布

问题:

I'm in a problem using Promise.all().

I'd like to pass an array variable as an argument to Promise.all() like below.

const promArr = []
if (condition1) {
  promArr.push(() => prom1(arg1, arg2))
}
if (condition2) {
  promArr.push(() => prom2(arg1, arg2))
}
if (promArr.length > 0) Promise.all(promArr)

But above doesn't run the promise functions(prom1, prom2) even if conditions are all true. (promArr.length is as I expected)

if I push promise functions directly to promArr, I'm afraid they run at that time they are pushed to promArr, not at Promise.all(promArr).

How can I use Promise properly in this case?

回答1:

Using a promArr variable is just fine. However (as the name suggests), it should be an array of promises, not an array of functions that return promises.

const promArr = []
if (condition1) {
  promArr.push(prom1(arg1, arg2))
}
if (condition2) {
  promArr.push(prom2(arg1, arg2))
}
return Promise.all(promArr)

if I push promise functions directly to promArr, I'm afraid they run at that time they are pushed to promArr, not at Promise.all(promArr).

Promise.all won't run any functions, you have to do it yourself. Yes, by calling prom1 and prom2 immediately inside the conditional block, they will start right after the condition is evaluated, but if they're properly asynchronous and don't interfere with the following conditions that is not a problem. Notice that the promises they return are not awaited yet, they'll do their processing in parallel.



回答2:

According to the MDN, Promise.all() returns a single Promise that resolves when all of the promises in the iterable argument have resolved [...].

Try to push Promises :

promArr.push(new Promise((resolve, reject) => {
    console.log(p1, p2);
}));

If I use your example, I get :

const p1 = 1;
const p2 = 2;
const promArr = [];

if (condition1)
  promArr.push(new Promise((resolve, reject) => {
    console.log(p1, p2);
}));

if (condition2)
  promArr.push(new Promise((resolve, reject) => {
    console.log(p1, p2);
}));

Promise.all(promArr);

if I push promise functions directly to promArr, I'm afraid they run at that time they are pushed to promArr, not at Promise.all(promArr).

If you want to run all functions at Promise.all, you can do something like that :

const p1 = 1;
const p2 = 2;
const promArr = [];

if (condition1)
  promArr.push(() => prom1(arg1, arg2));
if (condition2)
  promArr.push(() => prom1(arg1, arg2));

Promise.all(promArr.map((prom) => new Promise((resolve) => resolve(prom()))));

Here, the .map transform the array of function into an array of promises who is given to the Promise.all().

That's a bit tricky but it's working.