节点; Q 承诺延迟

Node; Q Promise delay

这里有一些简单的问题,这些问题基于我在以下示例中注意到的行为 运行 in node:

Q('THING 1').then(console.log.bind(console));
console.log('THING 2');

此输出为:

> "THING 2"
> "THING 1"

问题:

1) 为什么 Q 实现为在 运行 立即知道的值的回调之前等待?为什么 Q 不够聪明以允许第一行在第二行运行之前同步发出其输出?

2) "THING 2""THING 1" 输出之间的时间间隔是多少?是单进程tick吗?

3) 深深包裹在承诺中的价值观是否会带来性能问题?例如,Q(Q(Q("THING 1"))) 是否异步等待 3 倍的时间才能完成,即使它可以有效地同步解决?

这其实是故意的。就是为了让这个值已知与否保持一致。这样只有一个评估顺序,你可以依赖这样一个事实,即无论 promise 是否已经结算,该顺序都是相同的。

此外,如果不这样做,可以编写代码来测试承诺是否已经解决,并且根据设计,它不应该被知道和采取行动。

这几乎就是像这样的回调式代码:

function fun(args, callback) {

    if (!args) {
        process.nextTick(callback, 'error');
    }
    // ...
}

这样调用它的任何人:

fun(x, function (err) {
  // A
});
// B

可以肯定A永远不会运行先于B.

规范

参见 Promises/A+ Specification, The then Method 部分,第 4 点:

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

另见 the note 1:

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.

所以这实际上是规范规定的。

已进行广泛讨论以确保此要求明确 - 参见: