Artheg
Artheg

Reputation: 25

Can I push new promise into array in the middle of Promise.all()?

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

Answers (2)

T.J. Crowder
T.J. Crowder

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

Jonas Wilms
Jonas Wilms

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

Related Questions