【问题标题】:ES6 promise execution orderES6 承诺执行顺序
【发布时间】:2016-04-10 06:31:51
【问题描述】:

我希望以下 sn-p 的输出为 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);
  });
});

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

我读过的所有关于 Promise 的内容都表明应该可以在这样的“扁平”链中获得所需的顺序。显然我遗漏了一些细节?有人可以帮我指出正确的方向吗?

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

我已经搜索了有关堆栈溢出的类似问题,但没有一个使用简单的示例(我可以找到)笼统地回答这个问题。

【问题讨论】:

  • 你的意思是self.promiseChain = self.promiseChain.then...
  • 是的@elclanrs,看起来那是我的问题!

标签: javascript ecmascript-6 es6-promise


【解决方案1】:

您刚刚将三个.then() 处理程序附加到完全相同的self.promiseChain 承诺。这是分支,而不是链接。有了承诺,这些都是非常不同的行为。当self.promiseChain 被解析时,这三个处理程序将一个接一个地被调用(不等待结果)。因此,生成的三个异步操作将并行运行并在它们完成时完成,因此您会看到结果。

如果您希望这四个操作被排序,那么您必须将它们实际链接到另一个,而不是全部链接到同一个 Promise。请记住 .then() 返回一个新的 Promise,它是您想要链接到的返回的 Promise 以便对事物进行排序。

你正在这样做:

var p = somePromise();

p.then(fn1);
p.then(fn2);
p.then(fn3);

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

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

var p = somePromise();

p.then(fn1).then(fn2).then(fn3);

在完成fn1 承诺之前,这不会执行fn2,并且在完成fn2 承诺之前不会执行fn3 - 从而对异步操作进行排序。

如果它们实际上是一个接一个地排序,情况会是这样。你实际上可以运行这个 sn-p (但要有耐心,因为它需要 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);
}

查看其他类似的答案:

Execute native js promise in series

Understanding javascript promises; stacks and chaining

Is there a difference between promise.then.then vs promise.then; promise.then

【讨论】:

  • 谢谢你,@jfriend00!我想我可以理解反对票。我想我应该复习一下我的 stackoverflow 搜索技巧。无论如何,我的误会现在已经很清楚了,我终于可以从键盘上抬起头了!
猜你喜欢
  • 2018-03-06
  • 1970-01-01
  • 2017-01-13
  • 2018-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-30
相关资源
最近更新 更多