无关的承诺解决订单保证

时间:2016-05-25 16:57:01

标签: promise bluebird

我想知道以下是否是根据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;
});

问题是,在标记为then的{​​{1}}回调之前是否保证标记为(1)的{​​{1}}回调。

请注意,所有相关的承诺都会立即得到解决,因此在我看来then然后应该将调用作为调用(2)的一部分进行调度,这应该在用于解析{的承诺之前{1}}已解决,因此应该在安排(1)之前解决。

https://jsfiddle.net/m4ruec7o/

一起玩的示例jsfiddle

似乎这是bluebird> = 2.4.1所发生的情况,而不是之前的版本。我跟踪了此提交的行为更改:https://github.com/petkaantonov/bluebird/commit/6bbb3648edb17865a6ad89a694a3241f38b7f86e

谢谢!

1 个答案:

答案 0 :(得分:0)

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

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

如果要在两个独立的承诺链之间指示执行顺序,那么您必须以某种方式链接它们,以便在其他操作完成之前不会运行一个操作。您可以直接链接两个链,也可以执行更复杂的操作,包括插入到一个链中的中间承诺,以便在解析之前阻止该链。

您可能会发现这个答案很有用What is the order of execution in javascript promises,它提供了对链式和独立承诺的执行顺序的逐行分析,并讨论了如何使执行顺序可预测。