Reputation: 25
I'm trying to figure out how Promise.all works. My question is: is that ok to push a new promise in the middle of Promise.all() into the same array that was passed earlier? For example, I have this code which works just fine: https://jsfiddle.net/artheg/z0Lndw1o/14/
const promises = [];
const promise1 = new Promise(function(resolve, reject) {
resolve('promise1');
const promise2 = new Promise(function(resolve, reject) {
resolve('promise2');
});
pushPromise(promise2); // Pushing promise2 to the same array after the promise1 was resolved
});
pushPromise(promise1); // Pushing promise1
function pushPromise(promise) {
promises.push(promise);
}
Promise.all(promises).then(function(values) {
console.log(values); // Array [ "promise2", "promise1" ]
});
Is this behavior intended or should I always chain promises with .then() instead of pushing a new Promise into the array?
Upvotes: 1
Views: 142
Reputation: 1074266
The code in a promise executor (the function you pass new Promise
) runs synchronously. So pushPromise(promise2)
has already run before you call Promise.all
. The array is already filled by the time you call Promise.all
.
Can I push new promise into array in the middle of Promise.all()?
Not if you want Promise.all
to see that promise, no. See the specification, Promise.all
loops through the iterable you pass it synchronously, before returning, and before any handlers it (Promise.all
) sets up on the promises can be called.
Here's an example, note that the promise from Promise.all
is fulfilled rather than rejecting, even though the code adds a promise to the array that it rejects:
const promises = [
Promise.resolve(1),
Promise.resolve(2).finally(() => {
promises.push(Promise.reject(new Error("failed")));
}),
Promise.resolve(3),
];
Promise.all(promises)
.then(results => {
console.log(`results (${results.length}): ${results.join(", ")}`);
console.log(`promises.length: ${promises.length}`);
})
.catch(error => {
console.error(error);
});
Upvotes: 2
Reputation: 138267
That's because you push the promises to the array synchronously. Promise.all
works with the promises that are in the array by the time you pass it in.
Example of a Promise added asynchronously:
const promises = [Promise.resolve(1)];
setTimeout(() => promises.push(Promise.resolve(2)), 0);
Promise.all(promises).then(console.log); // [1]
Upvotes: 1