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

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

本文关键字:解决 Promise all array 为什么      更新时间:2023-09-26

我在机器上运行下面的代码示例(安装了 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> }
承诺 { [ 未定义, 未定义 ] }

为什么 p12 在 p1 和 p2

之后没有立即解析(在程序开始时解决 p1 和 p1),为什么"超时"p12 被解析了?解决 Promise.all(array) 是否需要一些时间?

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

console.log(p12);

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


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

根据承诺/A+ 规范:

在执行之前不得调用 onFulfilling 或 onReject 上下文堆栈仅包含平台代码。

这里的"平台代码"意味着引擎、环境和承诺 实现代码。在实践中,这一要求确保了 onFulfilled 和 onReject 在事件发生后异步执行 循环转弯,然后调用,并带有新的堆栈。这可以是 使用"宏任务"机制(如 setTimeout 或 set即时,或使用"微任务"机制,例如 MutationObserver 或 process.nextTick.自承诺实施以来 被认为是平台代码,它本身可能包含任务调度 队列或"蹦床",其中调用处理程序。

因此,所有这一切的结果是,承诺总是在当前执行线程完成后异步解析。 虽然内部细节可能比这复杂一些(可能涉及微任务),但从逻辑上讲,你可以通过将一条消息发布到事件队列来考虑一个承诺,它现在正在等待被解决/拒绝。 而且,每当事件队列完成当前正在运行的内容并轮到运行承诺.then()处理程序时,它们才会执行。