节点; Q承诺延迟
以下是一些简单的问题,这些问题基于我在以下运行在节点中的示例中注意到的行为:
Q('THING 1').then(console.log.bind(console));
console.log('THING 2');
这个输出是:
> "THING 2"
> "THING 1"
问题:
1)为什么Q
在执行回调之前等待立即知道的值? 为什么Q
不够聪明,让第一行在第二行之前同步发出它的输出?
2)输出"THING 2"
和"THING 1"
之间的时间间隔是多少? 它是一个单独的过程打勾吗?
3)对承诺中包含的价值观有没有性能问题? 例如, Q(Q(Q("THING 1")))
异步等待3倍的时间才能完成,即使它可以有效地同步解决?
这实际上是有目的地完成的。 无论价值是否已知,都要保持一致。 这样只有一个评估顺序,您可以依赖的事实是,无论承诺是否已经解决,该订单都是一样的。
另外,否则就可以编写一段代码来测试承诺是否已经解决,并且通过设计它不应该被了解和采取行动。
这几乎就像做这样的回调式代码:
function fun(args, callback) {
if (!args) {
process.nextTick(callback, 'error');
}
// ...
}
以便任何人通过以下方式进行通话:
fun(x, function (err) {
// A
});
// B
可以确定A永远不会在B之前运行。
规格
请参阅承诺/ A +规范, then
方法部分,点4:
在执行上下文堆栈仅包含平台代码之前,不能调用onFulfilled
或onRejected
。
另见附注1:
这里“平台代码”是指引擎,环境和承诺实现代码。 实际上,这个要求确保onFulfilled和onRejected异步执行,在事件循环开始之后被调用,并且有新的堆栈。 这可以使用诸如setTimeout或setImmediate之类的“宏任务”机制或者使用诸如MutationObserver或process.nextTick的“微任务”机制来实现。 由于承诺实现被认为是平台代码,因此它本身可能包含调用处理程序的任务调度队列或“蹦床”。
所以这实际上是由规范所要求的。
为了确保这一要求很明确,广泛讨论了这一点 - 请参阅: