繁体   English   中英

为什么Promise.all(数组)没有立即解决?

[英]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);

结果:

承诺{undefined}
承诺{undefined}
承诺{ <pending> }
承诺{[undefined,undefined]}

为什么在p1和p2之后没有立即解析p12(在程序开始时解析p1和p1),为什么“timeouted”p12得到解决? Promise.all(数组)需要一些时间才能得到解决吗?

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

console.log(p12);

表明承诺仍然“待定”。 它是当前的.then()处理程序(如果有的话)还没有被调用。 但是,一旦当前的代码线程完成执行并且控制返回到事件队列中的下一个事件,则将解析promise,因此你的setTimeout()将其视为已解决。


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

来自Promises / A +规范

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

这里的“平台代码”意味着引擎,环境和承诺实现代码。 实际上,这个要求确保onFulfilled和onRejected异步执行,然后调用事件循环,然后调用新堆栈。 这可以使用诸如setTimeout或setImmediate之类的“宏任务”机制,或者使用诸如MutationObserver或process.nextTick之类的“微任务”机制来实现。 由于promise实现被认为是平台代码,因此它本身可能包含一个任务调度队列或“trampoline”,其中调用处理程序。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM