ES6承诺执行顺序

l p*_*l p 3 javascript ecmascript-6 es6-promise

我希望以下代码段的输出是1, 2, 3, 4.但是,实际的输出顺序是1, 4, 3, 2.

self.promiseChain = new Promise(function (resolve, reject) {
  setTimeout(resolve, 4000);
}).then(function () {
  console.log(1);
});

self.promiseChain.then(function () {
  return new Promise(function (resolve, reject) {
    setTimeout(resolve, 3000);
  }).then(function () {
    console.log(2);
  });
});

self.promiseChain.then(function () {
  return new Promise(function (resolve, reject) {
    setTimeout(resolve, 2000);
  }).then(function () {
    console.log(3);
  });
});
self.promiseChain.then(function () {
  return new Promise(function (resolve, reject) {
    setTimeout(resolve, 200);
  }).then(function () {
    console.log(4);
  });
});
Run Code Online (Sandbox Code Playgroud)

http://www.es6fiddle.net/imu5bhoj/

我所读到的关于承诺的一切表明应该可以在这样的"扁平"链中获得所需的订单.显然我错过了一些细节?有人能指点我正确的方向吗?

这是一个小提琴(http://www.es6fiddle.net/imu6vh1o/),关于如何以非平坦的方式进行,但它更难以推理并使顺序链接变得尴尬.

我已经在堆栈溢出中搜索了类似的问题,但是他们都没有使用一个直截了当的例子(我能找到)来回答这个问题.

jfr*_*d00 9

你只是将三个.then()处理程序附加到完全相同的self.promiseChain承诺上.这是分支,而不是链接.有了承诺,那些是非常不同的行为.这三个处理程序将在self.promiseChain解决后立即被一个接一个地调用(无需等待结果).因此,生成的三个异步操作将并行运行,并在完成时完成,从而得到您看到的结果.

如果你想对这四个操作进行排序,那么你必须将它们彼此链接起来,而不是全部链接到同一个承诺上.记住.then()返回一个新的promise,它是你想要链接的返回的promise,以便对事物进行排序.

你这样做:

var p = somePromise();

p.then(fn1);
p.then(fn2);
p.then(fn3);
Run Code Online (Sandbox Code Playgroud)

这将触发fn1,fn2并且fn3基本上同时并且fn2不会等待fn1承诺解决.

如果要对操作进行排序,那么您需要这种类型的逻辑:

var p = somePromise();

p.then(fn1).then(fn2).then(fn3);
Run Code Online (Sandbox Code Playgroud)

这将fn2fn1promise完成后才会执行fn3,并且在fn2promise完成之前不会执行- 从而对异步操作进行排序.

如果它们实际上是一个接一个地排序的话,它会是怎样的.您实际上可以运行此代码段(但需要耐心,因为它需要10秒才能运行):

var self = {};

self.promiseChain = new Promise(function (resolve, reject) {
  setTimeout(resolve, 4000);
}).then(function () {
  log(1);
});

var p = self.promiseChain.then(function () {
  return new Promise(function (resolve, reject) {
    setTimeout(resolve, 3000);
  }).then(function () {
    log(2);
  });
});

p = p.then(function () {
  return new Promise(function (resolve, reject) {
    setTimeout(resolve, 2000);
  }).then(function () {
    log(3);
  });
});
p = p.then(function () {
  return new Promise(function (resolve, reject) {
    setTimeout(resolve, 200);
  }).then(function () {
    log(4);
  });
});

p.then(function() {
   // last promise is done now
   log("all done");
});

function log(x) {
  var div = document.createElement("div");
  div.innerHTML = x;
  document.body.appendChild(div);
}
Run Code Online (Sandbox Code Playgroud)

看到这些其他类似的答案:

在系列中执行本机js promise

理解javascript承诺; 堆叠和链接

promise.then.then与promise.then之间有区别吗?promise.then