承诺连锁订单

时间:2016-06-05 12:24:16

标签: javascript promise bluebird

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

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

我想这发生了,因为函数是resolved然后他继续next function我是否正确?如果这是真的,我怎么能做这个链,当第一个完成then他进入第二个等但没有使用承诺地狱:-)

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);
   });

3 个答案:

答案 0 :(得分:3)

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

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

如果没有这个,你只是在没有“阻止”的情况下调用每个步骤来解决上一步。

答案 1 :(得分:2)

我知道你已经得到了一个答案,说明为什么你原来的代码没有用,但我想我会用另一种方法来解决它比你更干的方法在做。您可以创建一个返回函数的函数,然后您可以按照您正在使用的方式使用它,因为它返回的函数将在稍后调用,这是.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/

答案 2 :(得分:1)

丹尼尔怀特的评论和回答是正确的,但我认为另外的解释可能有所帮助。

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

  1. then无法接受承诺,但它可以采用返回承诺的功能。如果您传入除函数之外的任何内容,它将被忽略,就像您传入null一样。
  2. 只要您调用new Promise(someFunction)someFunction就会异步执行而无需等待任何内容。这意味着您可以在new Promise功能中拨打then,但如果您提前致电,则不会有您期望的延迟行为。
  3. 因此,每次调用stepN都会返回一个新构建的承诺,我已经内联了所有同步发生的内容,并重命名了结果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);
       });