简体   繁体   English

嵌套承诺实现顺序执行

[英]Nested promises to achieve sequential execution

I have a function that calls itself a couple of times when a promise is resolved, and when it is done calling itself, it resolves the promise like so: 我有一个函数,当一个诺言被解决时,它会多次自我调用,当它完成自身的调用后,它会像下面这样对诺言进行解析:

var counter = 0;
function runStep(past_resolved_content) {
  return new Promise(function(resolve, reject){
  //do something different with counter
  if (counter < reference ) {
    counter++;
    var step_ran = somePromiseReturningFunction();
    step_ran.then(runStep);
  } else {
    resolve("message");     
  }

From what I can tell, the function does what I want, it will call the somePromiseReturningFunction() correctly and in the desired order. 据我所知,该函数执行了我想要的操作,它将正确且按所需顺序调用somePromiseReturningFunction() I have a second function that must call runStep() and continue execution when the promise returned by it is resolved. 我有第二个函数,必须调用runStep()并在其返回的诺言得到解决时继续执行。

function executeAllSteps() {
  runStep().then(
    function(){
      console.log("resolved outer promise");
  });
}

My problem is that I cannot make the executeAllSteps function work as desired. 我的问题是我无法使executeAllSteps函数正常工作。 I have tried several syntax for the .then but nothing produced the desired output. 我已经为.then尝试了几种语法.then但是没有任何东西产生所需的输出。

Either the content is called immediately, without the promise resolving ( when I write it like this: runStep().then(console.log("resolved outer promise")); , or never at all. 要么立即调用内容,而没有解决承诺(当我这样写时: runStep().then(console.log("resolved outer promise"));或者根本不会。

Does anyone know how to correct this function? 有人知道如何纠正此功能吗?

Note: I need to use the native javascript promise implementation. 注意:我需要使用本地javascript promise实现。

Once you go inside the if (counter < reference ) { condition, you will never resolve the promise that you created in that invocation of runStep() and thus the .then() handler in executeAllSteps() never fires. 一旦进入if (counter < reference ) {条件,您将永远无法解析在runStep()调用中创建的承诺,因此executeAllSteps()runStep() .then()处理函数将永远不会触发。 You need to find a place in runStep() where you resolve the promise you created for each invocation of runStep() , whether or not you've reach your counter max. 您需要在runStep()中找到一个位置,在这里您可以解决为每次调用runStep()创建的承诺,无论您是否达到计数器最大值。

I'm not sure I fully understand what you're trying to achieve, but you could do this: 我不确定我是否完全理解您要实现的目标,但是您可以这样做:

var counter = 0;
function runStep(past_resolved_content) {
  return new Promise(function(resolve, reject) {
    //do something different with counter
    if (counter < reference ) {
      counter++;
      var step_ran = somePromiseReturningFunction();
      step_ran.then(runStep).then(resolve);          // <== change made here
    } else {
      resolve("message");     
    }
  });
}

Logically, this will call call the first runStep() which will execute somePromiseReturningFunction() and when that is done (when it's promise is resolved), it will call a nested runStep() and when that inner runStep resolves, the outer one will resolve itself. 从逻辑上讲,这将调用调用第一个runStep() ,它将执行somePromiseReturningFunction() ,完成后(当诺言得到解决时),它将调用嵌套的runStep() ,当内部runStep解析后,外部的将解析本身。 So what will happen is you will nest several calls to runStep() until your counter gets to the reference value and then that inner runStep will resolve itself. 因此,将发生以下情况:您将嵌套多次调用runStep()直到counter达到reference值,然后内部runStep将自行解决。 That will allow the next-most outer runStep to resolve itself, then the next most outer runStep to resolve itself continuing until it gets to the most outer runStep which will resolve itself and then all then .then() handler in executeAllSteps() which it sounds like is what you want. 这将使下一个最外runStep自行解决,那么接下来最外runStep解决自身持续,直到它到达最外runStep它会自己解决问题,然后将所有然后.then()在处理executeAllSteps()它听起来像是您想要的。


I suspect that if I understood more what you're really trying to accomplish rather than this somewhat abstract code example, then I could probably find a much cleaner way to do this, but I don't really follow what you want to do in what conditions. 我怀疑如果我了解更多您真正想完成的事情,而不是这个抽象的代码示例,那么我可能会找到一种更简洁的方法来执行此操作,但是我并没有真正遵循您想做什么条件。


There are several different approaches you could take that will use existing promises rather than always creating new ones. 您可以采用几种不同的方法,这些方法将使用现有的承诺而不是总是创建新的承诺。 Here's one idea: 这是一个主意:

var counter = 0;
function runStep(past_resolved_content) {
    //do something different with counter
    if (counter < reference ) {
        counter++;
        return somePromiseReturningFunction().then(runStep);
    } else {
        // return a resolved promise with your message
        return Promise.resolve("message");
        });
    }
}

You could also avoid calling runStep recursively when the counter has reached its value which simplifies things a bit (assumes you don't call runStep the first time when counter has already exceeded the value): 您还可以避免在计数器达到其值时递归调用runStep,从而稍微简化了一些事情(假设您在计数器已经超过该值时第一次不调用runStep):

var counter = 0;
function runStep(past_resolved_content) {
    counter++;
    return somePromiseReturningFunction().then(function(data) {
        if (counter < reference) {
            return runStep(data);
        } else {
            return data;
        }
    });
}

Working demo of this idea: http://jsfiddle.net/jfriend00/PfEV2/ 这个想法的工作演示: http : //jsfiddle.net/jfriend00/PfEV2/


And, if you don't need to manipulate the counter variable as the process unfolds, then you could do it in a loop too where runStep doesn't have to call itself and the counter doesn't have to be a public variable: 而且,如果您不需要在进程展开时操纵counter变量,那么您也可以在循环中执行此操作,其中runStep不必调用自身,并且计数器不必是公共变量:

function runStep() {
    var p = Promise.resolve();
    for (var counter = 0; counter < reference; counter++) {
        p = p.then(somePromiseReturningFunction);
    }
    return p;
}

Working demo: http://jsfiddle.net/jfriend00/33ZZ6/ 工作演示: http : //jsfiddle.net/jfriend00/33ZZ6/

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

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