Why do promises execute at the point of declaration?

我是研究僧i 提交于 2021-02-19 03:11:30

问题


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
*/

回答1:


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.




回答2:


Yes, promises execute right away. They couldn't work any other way. Promises, just like any other object in JS, are completely unaware of what is referencing them and how they get passed around, so there's no way for them to "wait" until something particular is getting done with the references to them.

The solution in your case is to create the promises as you pass them to Promise.all():

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

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

console.log('start')
Promise.all(promiseFnArray.map(promiseFn => new Promise(promiseFn));

Also, once your promises actually make something asynchronous, they won't necessarily resolve in the original order. To get the results in the correct order you use Promise.all( ... ).then(), which is the entire purpose of Promise.all()



来源:https://stackoverflow.com/questions/49685779/why-do-promises-execute-at-the-point-of-declaration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!