嵌套承诺实现顺序执行

Nested promises to achieve sequential execution

本文关键字:执行 顺序 实现 承诺 嵌套      更新时间:2023-09-26

我有一个函数,当一个承诺被解析时,它会调用自己几次,当它完成调用自身时,它会像这样解析承诺:

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

据我所知,该函数可以执行我想要的操作,它将按照所需的顺序正确调用somePromiseReturningFunction()。我有第二个函数,它必须调用runStep()并在解析它返回的承诺时继续执行。

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

我的问题是我无法使executeAllSteps功能按预期工作。我已经为.then尝试了几种语法,但没有产生所需的输出。

要么立即调用内容,而不解决承诺(当我这样写时:runStep().then(console.log("resolved outer promise"));,或者根本不调用。

有谁知道如何纠正此功能?

注意:我需要使用原生的javascript承诺实现。

一旦你进入if (counter < reference ) {条件,你将永远无法解决你在runStep()调用中创建的承诺,因此executeAllSteps()中的.then()处理程序永远不会触发。 你需要在runStep()找到一个地方,在那里你解决你为每次调用runStep()创建的承诺,无论你是否达到了你的计数器最大值。

不确定我是否完全理解您要实现的目标,但您可以这样做:

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

从逻辑上讲,这将调用将执行somePromiseReturningFunction()的第一个runStep(),当它完成时(当它的承诺被解析时(,它将调用一个嵌套runStep()当内部runStep解析时,外部将自行解析。 因此,将要发生的事情是,您将嵌套多个调用以runStep(),直到您的counter达到reference值,然后该内部runStep将自行解决。 这将允许下一个最外在的runStep自行解析,然后下一个最外在的runStep继续解析自身,直到它到达最外在的runStep,它将自行解析,然后.then() executeAllSteps()的处理程序听起来是你想要的。


怀疑如果我更多地了解你真正想要完成的事情,而不是这个有点抽象的代码示例,那么我可能会找到一种更干净的方法来做到这一点,但我并没有真正遵循你想在什么条件下做什么。


您可以采取几种不同的方法,使用现有承诺,而不是总是创建新承诺。 这里有一个想法:

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

您还可以避免在计数器达到其值时递归调用 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;
        }
    });
}

这个想法的工作演示:http://jsfiddle.net/jfriend00/PfEV2/


而且,如果你不需要在过程展开时操作counter变量,那么你也可以在循环中进行操作,runStep不必调用自己,计数器也不必是公共变量:

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

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