Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do promises execute at the point of declaration?

I would like to execute a set of promises using Promise.all(). My approach is to put these promises in an array and then pass the array to Promise.all(). However, I find that the promises start executing as soon as they are declared and do not even wait for Promise.all to be called.

Why is this happening and how can I have the promises only execute upon calling Promise.all()?

let promiseArray = [];
const values = [1, 2, 3, 4, 5];

values.forEach((value)=>{
  promiseArray.push(
    new Promise((resolve, reject)=>{
      console.log('value: ' + value);
      return resolve();
    })
  )
})


console.log('start')
Promise.all(promiseArray)

/*
 output is 

  value: 1
  value: 2
  value: 3
  value: 4
  value: 5
  start

 would have expected output to have been

  start
  value: 1
  value: 2
  value: 3
  value: 4
  value: 5
*/
like image 564
takinola Avatar asked Jan 28 '23 08:01

takinola


1 Answers

Thinking of promises as "executing" is getting you confused. A promise is purely a notification mechanism. It is typically tied to some underlying asynchronous operation and when you create the promise, the asynchronous operation is typically started.

Promise.all() is then used to track when a whole bunch of asynchronous operations that you've already started have completed (or ended with an error).

So, you don't use Promise.all() to start a bunch of things. You use it just to track when they are all done and they are started elsewhere in your code.


When you manually create a promise with new Promise(), the promise executor is executed immediately. That's how they are designed.

If you had real asynchronous operations in your promise executor and you were doing console.log() when those operations completed, you'd probably not find any issue with how promises are designed. I think most of your confusion stems from the fact that you don't actually have any asynchronous operation inside your promise executor and thus there's really no reason to even use a promise for that. Promises are designed to track the completion of asynchronous operations. No reason to use them if you don't have an actual asynchronous operation.

FYI, if you want to start some asynchronous operation at some time in the future from inside the promise executor, you can use the normal setTimeout() or process.nextTick() or setImmediate() operations to schedule the operation to start later.

would have expected output to have been

Plus, it appears you are expecting your output to be in a strict order. Promise.all() expects there to be N asynchronous operations running in parallel and there is no guaranteed order of completion for those N operations. Instead, Promise.all() will track them all, collect all the results and present the .then() handler with an array of results in order (if they all resolved successfully). It does not run the operations themselves in order. The operations run in parallel and complete in whatever natural order they take.

like image 176
jfriend00 Avatar answered Jan 31 '23 09:01

jfriend00