为什么 Promise.all(array) 没有立即解析?

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

我运行我的机器上的代码示例(安装了 Node 5.8.0)并得到下一个结果(见代码示例之后)。

代码示例:

'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);

结果:

承诺{未定义}
承诺{未定义}
承诺{<pending>}
承诺 { [ undefined, undefined ] }

为什么 p12 没有在 p1 和 p2 之后立即解析(在程序开始时给出 p1 和 p1 解析),为什么 'timeouted' p12 被解析了? 解析 Promise.all(数组) 是否需要一些时间?

根据承诺规范,承诺履行或拒绝处理程序始终在事件循环完成其当前周期后异步调用。因此,p12 不会立即得到解决,即使它的参数都是已解决的承诺。因此,直到此事件循环结束后不久,它才会得到解决。这解释了为什么你的第一个声明:

console.log(p12);

表明承诺仍然是"pending"。当前 .then() 个处理程序(如果有)尚未被调用。但是,一旦当前代码线程完成执行并将 returns 控制回事件队列中的下一个事件,承诺将被解决,因此您的 setTimeout() 认为它已解决。


这样做是出于调用者一致性的原因,以便 .then() 处理程序以异步方式一致地被调用,无论承诺是否已经解决或尚未解决。这允许调用代码始终一致地编码,而不必担心承诺是否已经解决。在所有情况下,.then() 处理程序在当前堆栈展开并完成后被调用。

来自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.

因此,所有这一切的结果是,承诺总是在当前执行线程完成后异步解决。尽管内部细节可能比这复杂一点(可能涉及微任务),但您可以从逻辑上考虑通过向事件队列发布一条消息来解决它现在正在等待 resolved/rejected 的承诺。并且,每当事件队列完成当前 运行ning 并转向 运行 承诺 .then() 处理程序时,它们才会执行。