【问题标题】:What does "Promise fires on the same turn of the event loop" mean?“Promise 在事件循环的同一回合触发”是什么意思?
【发布时间】:2015-04-29 06:19:53
【问题描述】:

NodeJS 新手。浏览承诺教程('promise-it-wont-hurt')我有以下脚本:

var Q = require('q');
var deferred = Q.defer();
deffered.resolve('SECOND');
deffered.promise.then(console.log);
console.log('FIRST');

输出:

FIRST
SECOND

我不明白,我原以为既然已经解决了,我应该先看到第二个。

他们解释说这是因为“Promise 在事件循环的同一轮触发”。我不明白这是什么意思...

【问题讨论】:

  • 这不是重复的>:(。问题不在于事件循环如何工作,而在于如何实现 Promise。
  • 问题包含错误。 Promise 永远不会在事件循环的同一轮中触发——它们总是会在 随后的轮中触发!

标签: javascript node.js q


【解决方案1】:

他们解释说这是因为“Promise 在事件循环的同一轮触发”。我不明白这是什么意思...

我也是,恕我直言,这部分没有多大意义。大概应该是说,当你调用resolve或者reject的时候,promise会立即结算,从此不会改变它的状态。这与回调无关。

更重要的是要理解的是该段中的下一句话:

您可以预期,传递给 promise 的“then”方法的函数将在事件循环的 NEXT 轮次中被调用。

这就像一个简单的经验法则:then 回调总是异步调用。始终,在每一个适当的承诺实施中;这是Promises/A+ specification 规定的。

这是为什么?为了一致性。与您的示例 sn-p 不同,您不知道如何或何时解决承诺 - 您只是从您调用的某个方法中将其返回。它可能已经解决,或者可能仍在等待中。现在你调用 promise 的 then 方法,你可以知道:它将是异步的。您无需处理 might be synchronous or not 并更改代码含义的情况,它始终是异步的。

【讨论】:

  • 文本实际上并没有说“Promise 在事件循环的同一轮触发”。它说 “Promises/A+ 规范声明 Promises 不得在创建它们的事件循环的同一轮次触发它们的解析/拒绝功能。”,尽管不知何故“NOT”是@987654323 @.
  • 是的,我也有点期待缺少“不”。而且我只找到并阅读了this version,而不是官方的。真丢人。
  • 看起来 npm 上的版本也没有更新。它缺少“不”。
【解决方案2】:

基本上,关键是promise的then处理程序将不会在当前代码流完成执行并将控制权返回到执行环境(在本例中为节点)之前运行。

这是符合 Promises/A+ 的承诺的一个重要特征,因为它确保了可预测性。无论承诺是否立即解决:

function getAPromise() {
    var Q = require('q');
    var deferred = Q.defer();
    deferred.resolve('SECOND');
    return deferred.promise;
}

getAPromise().then(console.log);

console.log('FIRST');

或者是否在 10 秒后解决:

function getAPromise() {
    var Q = require('q');
    var deferred = Q.defer();
    setTimeout(function () {
        deferred.resolve('SECOND');
    }, 10000);
    return deferred.promise;
}

getAPromise().then(console.log);

console.log('FIRST');

您可以放心,FIRST 将始终被首先记录。

这在You don't know JS - async & performance 的第 2 章和第 3 章中有详细讨论。 有时异步运行而有时同步运行的异步操作称为Zalgos,不认为是好事。

重要的是要注意,jQuery 中广泛使用的 Promise 遵守此行为,并且也有 number of other problems。如果您发现自己有一个 jQuery 承诺,请将其包装在一个适当的承诺中并继续:

Q($.ajax(...)).then(breatheWithEase);

【讨论】:

  • 哇!感谢您提供出色的参考书!
猜你喜欢
  • 1970-01-01
  • 2014-01-20
  • 2017-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-18
  • 1970-01-01
  • 2016-08-04
相关资源
最近更新 更多