诺言链序

Promise chain order

我使用下面的代码,有些东西让我有点困惑 如果我输入 1000 毫秒的超时时间,我会看到 promise 以正确的顺序调用 但如果我将其更改为以下

  This is step 3 
  This is step 2 
  This is step 1

我想这是因为当函数是 resolved 然后他继续 next function 我是对的吗?如果这是真的,我怎么能做这个链,当第一个完成时 then 他继续第二个等等但没有使用 promise hell :-)

https://jsfiddle.net/2yym400j/

var step1 = function(ms) {
   return new Promise(function(resolve, reject) {
      setTimeout(function() {
         console.log("This is step 1");
         resolve();
      }, ms);
   })
}
var step2 = function(ms) {
   return new Promise(function(resolve, reject) {
      setTimeout(function() {
         console.log("This is step 2");
         resolve();
      }, ms);
   })
};
var step3 = function(ms) {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
         console.log("This is step 3");
         resolve();
      }, ms);
   })
};


step1(500)
   .then(step2(300))
   .then(step3(200))
   .catch(function(err) {
      console.log(err);
   });

只传递一个函数而不是步骤的结果。

step1(500)
   .then(function() { return step2(300); })
   .then(function() { return step3(200); })
   .catch(function(err) {
      console.log(err);
   });

没有这个,你只是在调用每个步骤,而没有 "blocking" 上一步来解决。

Daniel White 的评论和回答是正确的,但我认为额外的解释可能会有所帮助。

您的原始代码违反了两条规则:

  1. then 不能接受 Promise,但它可以接受 returns Promise 的函数。如果你传入函数以外的任何东西,它将被忽略,就像你传入 null 相反。
  2. 只要您调用 new Promise(someFunction)someFunction 就会异步执行,无需等待任何事情。这意味着您可以从 then 函数中调用 new Promise,但如果您提前调用它,那么它不会有您期望的延迟行为。

鉴于每次调用 stepN returns 都是一个新构造的承诺,我已经内联了所有同步发生的事情并重命名了结果 constructAndReturnPromiseNconstructedPromiseThatStepNReturns .这使得您的原始代码看起来像这样,所以所有的承诺都会立即发生:

constructedPromise1ThatStep1Returns
   .then(constructedPromise2ThatStep2Returns)  // BAD: Don't pass promises into then.
   .then(constructedPromise3ThatStep3Returns)  // BAD: Don't pass promises into then.
   .catch(function(err) {
      console.log(err);
   });

...Daniel White 的代码是这样做的:

constructedPromise1ThatStep1Returns
   // GOOD: The then function returns a promise that is *constructed inside* the function.
   .then(function() { return constructAndReturnPromise2(300); })
   .then(function() { return constructAndReturnPromise3(200); })
   .catch(function(err) {
      console.log(err);
   });

我知道您已经得到关于为什么您的原始代码不起作用的答案,但我想我会展示另一种方法来解决它,它比您正在做的更干。您可以创建一个 returns 函数的函数,然后您可以按照您使用的方式使用它,因为它 returns 一个稍后将被调用的函数,这正是 .then() 想要的。所以,你可以这样做:

function delay(t, msg) {
   return function() {
       return new Promise(function(resolve) {
           setTimeout(function() {
              console.log(msg);
              resolve();
           }, t);
       });
   }
}


delay(500, "This is step 1")()
   .then(delay(300,"This is step 2"))
   .then(delay(200, "This is step 3"))
   .catch(function(err) {
      console.log(err);
});

此处的工作演示:https://jsfiddle.net/jfriend00/mbpq4g8m/