Why the Promise.all(array) not resolved immediately?

I run the code sample bellow on my machine (with Node 5.8.0 installed) and get next result (see after the code sample).

Code sample:

  • Clean code and Nested promises
  • Using native ES6 promises with MongoDB
  • Promises propagating intermediate objects (NodeJS + MongoDB)
  • JS Promises: is there a neat way to resolve multiple promises as object properties?
  • ES5 vs ES6 Promises
  • How can I fetch an array of URLs with Promise.all?
  • 'use strict'
    
    var p1 = Promise.resolve();
    var p2 = Promise.resolve();
    
    var p12 = Promise.all([p1, p2]);
    
    var cb = function() {
      console.log(p12);
    }
    
    setTimeout(cb, 0);
    
    console.log(p1);
    console.log(p2);
    console.log(p12);
    

    Result:

    Promise { undefined }
    Promise { undefined }
    Promise { <pending> }
    Promise { [ undefined, undefined ] }

    Why is it so that p12 not resolved immediately after p1 and p2 (giving p1 and p1 resolved at the start of the program), and why is ‘timeouted’ p12 got resolved?
    Is there some amount of time needed for Promise.all(array) gets resolved?

  • how does promise resolution decide whether to treat a return value as a promise or as a plain value?
  • Use of Promises for sequential processing
  • ES6 Promise blocks page
  • Why does the Promise constructor require a function that calls 'resolve' when complete, but 'then' does not - it returns a value instead?
  • What is the use case of Promise.resolve(promise)?
  • Idiomatically handling pre-conditions with ES6 Promises
  • One Solution collect form web for “Why the Promise.all(array) not resolved immediately?”

    Per the promise specification, a promise fulfill or reject handler is always called asynchronously AFTER the event loop has finished its current cycle. Thus, p12 is not resolved immediately even though the arguments to it are all resolved promises. So, it won’t get resolved until shortly after this event loop finishes. This explains why your first statement:

    console.log(p12);
    

    shows that the promise is still “pending”. It’s current .then() handlers (if any) have not yet been called. However, once the current thread of code finishes executing and control returns back to the next event in the event queue, the promise will then be resolved and thus your setTimeout() sees it as resolved by then.


    This is done for caller consistency reasons so that .then() handlers are called consistently in an asynchronous manner no matter whether the promise was already resolved or is not yet resolved. This allows the calling code to always code consistently without worrying about whether the promise might already be resolved. In all cases .then() handlers are called after the current stack unwinds and finishes.

    From the Promises/A+ specification:

    onFulfilled or onRejected must not be called until the execution
    context stack contains only platform code.

    Here “platform code” means engine, environment, and promise
    implementation code. In practice, this requirement ensures that
    onFulfilled and onRejected execute asynchronously, after the event
    loop turn in which then is called, and with a fresh stack. This can be
    implemented with either a “macro-task” mechanism such as setTimeout or
    setImmediate, or with a “micro-task” mechanism such as
    MutationObserver or process.nextTick. Since the promise implementation
    is considered platform code, it may itself contain a task-scheduling
    queue or “trampoline” in which the handlers are called.

    So, the upshot of all this is that promises ALWAYS resolve asynchronously after the current thread of execution has finished. Though the internal details may be a bit more complicated than this (perhaps involving micro-tasks), you can logically think of a promise getting resolved by posting a message to the event queue that it is now awaiting being resolved/rejected. And, whenever the event queue finishes what is currently running and gets a turn to run the promises .then() handlers, only then will they execute.