0

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.

Ry-
  • 218,210
  • 55
  • 464
  • 476
Glen Pierce
  • 4,401
  • 5
  • 31
  • 50
  • Closely related: [Promise.all is returning an array of undefined and resolves before being done](/q/34813147/4642212), [Promise.all is not waiting for the functions to finish](/q/50994427/4642212). – Sebastian Simon Jan 26 '23 at 15:28

3 Answers3

2

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));
guest271314
  • 1
  • 15
  • 104
  • 177
  • Great, thanks! What are the ellipsis (...foo(1)) for? – Glen Pierce Feb 11 '17 at 19:49
  • 1
    @GlenPierce `...` punctuator can be spread element or rest element depending on usage, see [What is SpreadElement in ECMAScript documentation? Is it the same as Spread operator at MDN?](http://stackoverflow.com/questions/37151966/what-is-spreadelement-in-ecmascript-documentation-is-it-the-same-as-spread-oper). Without spread element, there will be three, or N-times `foo` calls arrays at array passed to `.then()` from `Promise.all()` instead of single array. `Promise.all([[1,2,3], [4,5,6]]).then(data => console.log(data)); Promise.all([...[1,2,3], ...[4,5,6]]).then(data => console.log(data))`. – guest271314 Feb 11 '17 at 19:52
1

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.

Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
1

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);
};
Ry-
  • 218,210
  • 55
  • 464
  • 476