How to use Promise.all() after Promises created in

2019-06-14 01:12发布

问题:

I have a function foo() that includes a Promise that resolves inside a for loop. I want to run foo() several times, giving it different arguments each time. Then I want to do something with the results of all of that. Will Promise.all() run at the end of the for loops or after all of the Promises inside of foo() returned? Or will it say "none of these foo()s are Promises!" and laugh at me?

var foo = (x) => {
    for (var i = 0; i < 100; i++) {
        someOtherFunctionThatReturnsAPromise(x).then(returnSomething());
    }
};

function nowDoEverything() {
    return Promise.all([foo(1), foo(2), foo(3)]).then(doSomethingWithAllThoseReturnedValues());
}

nowDoEverything();

Does foo() need to return a Promise? If so, how would I do so given that the Promises inside of foo() are generated inside the for loop?

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all states that "The Promise.all(iterable) method returns a promise that resolves when all of the promises in the iterable argument have resolved, or rejects with the reason of the first passed promise that rejects."

This video https://www.youtube.com/watch?v=RRgAdi3gX-s is really good at explaining basic Promises, but I seem to be trying to do something that the architects did not intend/expect.

回答1:

Push promises to an array, return array from foo, omit () from function within .then() to avoid calling function immediately. Use spread element at foo() calls to return a single array of promises to .then() chained to Promise.all().

var foo = (x) => {
    var arr = [];
    for (var i = 0; i < 100; i++) {
        arr.push(someOtherFunctionThatReturnsAPromise(x).then(returnSomething));
    }
    return arr
};

function nowDoEverything() {
    return Promise.all([...foo(1), ...foo(2), ...foo(3)])
           .then(doSomethingWithAllThoseReturnedValues)
}

nowDoEverything()
.catch(err => console.log(err));


回答2:

Yes, that's right. Here is the signature of Promise.all():

Promise.all<T>: (Iterable<Promise<T>): Promise<T[]>

Basically, it accepts an iterable of Promises, and returns itself a Promise.

By passing the results of foo(), foo() is expected to return a Promise itself, else it wouldn't work.



回答3:

Yes, foo() needs to return a promise. You can add each promise to an array and use Promise.all to wait for all of them:

var foo = x => {
    var results = [];

    for (var i = 0; i < 100; i++) {
        results.push(
            someOtherFunctionThatReturnsAPromise(x)
                .then(returnSomething)
        );
    }

    return Promise.all(results);
};