不相关的承诺解决订单保证

Unrelated Promise Resolution Order Guarantees

我想知道以下是否是根据 Promise 规范定义的行为:

var H = function (c) {
  this.d_p = Promise.resolve();
  this.d_c = c;
};

H.prototype.q = function () {
  var s = this;
  return new Promise(function (resolve) {
    s.d_p = s.d_p.then(function () {       // (1)
      s.d_c({
        resolve: resolve
      });
    });
  });
};

var a,
    h = new H(function (args) { a = args; }),
    p;

Promise.resolve()
.then(function () {
  p = h.q();
})
.then(function () {                        // (2)
  a.resolve(42);
  return p;
});

问题是是否保证标记为(1)then回调在标记为(2)then回调之前被调用。

请注意,有问题的两个承诺都会立即解决,所以在我看来 (1) 然后回调应该安排为调用 h.q() 的一部分,这应该在承诺之前resolve (2) 已解决,因此应该在安排 (2) 之前。

一个 jsfiddle 示例:https://jsfiddle.net/m4ruec7o/

这似乎是 bluebird >= 2.4.1 发生的情况,但不是以前的版本。我跟踪了这​​个提交的行为变化:https://github.com/petkaantonov/bluebird/commit/6bbb3648edb17865a6ad89a694a3241f38b7f86e

谢谢!

您可以保证 h.q() 会在 a.resolve(42); 被调用之前被调用,因为链式 .then() 处理程序会按顺序执行。

如果您询问的是 h.q() 中的代码,那么 s.d_p.then() 是完全不同的承诺链的一部分,并且承诺规范不提供单独承诺链的排序。它们可以自由地以自己的异步时序执行。而且,事实上,我已经看到在不同 Javascript 环境中独立承诺链的执行存在一些差异。

如果你想在两个独立的 promise 链之间引导执行顺序,那么你将不得不 link 它们以某种方式进行,这样一个操作不会 运行 直到其他操作完成。您可以直接 link 两条链,也可以做一些更复杂的事情,涉及插入一条链的中间承诺,以便它阻塞该链,直到它被解决。

您可能会发现此答案很有用 ,它逐行分析了链式和独立承诺的执行顺序,并讨论了如何使执行顺序可预测。