简体   繁体   English

承诺链订单

[英]Promise chain order

I use the following code and there is something that a bit confuse me if I put in the timeout 1000ms I see that the promise called in the right order but if I change it to the following 我使用以下代码,如果我将超时时间设置为1000ms,则会使我感到困惑,但是我看到按正确的顺序调用了promise,但是如果将其更改为以下内容

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

I guess that this happen since when the function is resolved then he proceed to the next function am I correct ? 我猜发生这种情况,因为当函数resolved后,他继续执行next function ,对吗? if this is true how can I do this chain that when the first is finished then he proceed to the second etc but without using the promise hell :-) 如果这是真的,我该怎么做,当第一个完成then他继续进行第二个操作,而不使用promise hell :-)

https://jsfiddle.net/2yym400j/ 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);
   });

Just pass a function instead of the result of the steps. 只需传递一个函数而不是步骤的结果即可。

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

Without this, you are just calling each step without "blocking" for the previous step to resolve. 如果没有此功能,您只需调用每个步骤,而不会“阻塞”上一步来解决。

I know you've already gotten an answer as to why your original code didn't work, but I thought I'd show another way to approach it that is a bit more DRY than what you were doing. 我知道您已经对为什么原始代码无法正常工作获得了答案,但是我想我将展示另一种方法来处理它,它比您正在执行的过程更加干燥。 You can create a single function that returns a function and then you can use that in the fashion you were using because it returns a function that will be called later which is what .then() wants. 您可以创建一个返回函数的函数,然后可以以您使用的方式使用该函数,因为它返回一个函数,该函数稍后将被.then()调用。 So, you can do something like this: 因此,您可以执行以下操作:

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

Working demo here: https://jsfiddle.net/jfriend00/mbpq4g8m/ 在这里工作的演示: https : //jsfiddle.net/jfriend00/mbpq4g8m/

Daniel White's comment and answer are correct, but I thought an additional explanation might help. 丹尼尔·怀特(Daniel White)的评论和回答是正确的,但我认为附加说明可能会有所帮助。

Your original code broke two rules: 您的原始代码违反了两个规则:

  1. then can't take a Promise, but it can take a function that returns a Promise. then就不能采用Promise,但是可以采用返回 Promise的函数。 If you pass in anything except a function, it will be ignored, just like you passed in null instead. 如果传入除函数以外的任何内容,它将被忽略,就像传入null
  2. As soon as you call new Promise(someFunction) , the someFunction executes asynchronously without waiting for anything. 调用new Promise(someFunction)someFunction异步执行,而无需等待任何操作。 This means you can call new Promise from within a then function, but if you call it early then it won't have the delayed behavior you're expecting. 这意味着您可以从then函数中调用new Promise ,但是如果您提前调用它,则不会有您期望的延迟行为。

So given that each call to stepN returns a newly-constructed promise, I've inlined everything that happens synchronously and renamed the results constructAndReturnPromiseN and constructedPromiseThatStepNReturns . 因此,鉴于对stepN每次调用stepN返回一个新构造的stepN ,所以我内联了所有同步发生的事情,并将结果重命名为constructAndReturnPromiseNconstructedPromiseThatStepNReturns That makes your original code looks like this so all the promises happen at once: 这使您的原始代码看起来像这样,因此所有承诺都会一次实现:

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

...where Daniel White's code does this: ...丹尼尔·怀特(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);
   });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM