【问题标题】:Managing sync and async functions in an algorithm call stack在算法调用堆栈中管理同步和异步函数
【发布时间】:2021-11-21 18:02:18
【问题描述】:

TLDR:如果大多数函数实际上不是async,我是否必须通过复杂的调用堆栈使用asyncawait?有替代的编程模式吗?

上下文

这个问题可能更多地是关于设计模式和整体软件架构,而不是特定的语法问题。我正在用 node.js 编写一个相当复杂的算法。程序流程涉及初始异步调用以获取一些数据,然后继续基于数据进行一系列同步计算步骤。计算步骤是迭代的,当它们迭代时,它们会产生结果。但有时,如果计算满足某些条件,则需要获取更多数据。这是图表形式的简化版本:

calcStep 循环同步运行数千次,推送结果。但有时它会跳回getData,程序必须等待更多数据进入,然后再继续执行calcStep 循环。

在代码中

上面的简化版本在 JS 代码中可能如下所示:

let data;

async function init() {
  data = await getData();
  processData();
  calcStep1();
}

function calcStep1() {
  // do some calculations
  calcStep2();
}

function calcStep2() {
  // do more calculations
  calcStep3();
}

function calcStep3() {
  // do more calculations
  pushToResults();

  if (some_condition) {
    getData(); // <------ question is here
  }

  if (stop_condition) {
    finish();
  } else {
    calcStep1();
  }
}

其中pushToResultsfinish 也是简单的同步函数。我在这里写的calcStep 函数是分开的,因为在实际代码中,它们实际上是基于关注点分离定义的类的类方法。

问题

出现了明显的问题,如果遇到some_condition,我需要等待获取更多数据才能继续calcStep循环,我需要在calcStep3中调用getData之前使用await关键字,这意味着calcStep3必须被称为async,我们必须在calcStep2中也必须await,并且一直到链上,即使是同步函数也必须标记为asyncawaited。

在这个简化的例子中,这样做不会太冒犯。但实际上,我的算法要复杂得多,调用堆栈要深得多,涉及许多类方法、迭代等。在这种情况下,有没有更好的方法来管理awaiting 函数?我可以使用的其他工具,例如生成器或事件发射器?我愿意接受简单的解决方案或范式转变。

【问题讨论】:

    标签: javascript node.js asynchronous design-patterns callstack


    【解决方案1】:

    如果您不想创建函数async 并将其传播到链上,请使用.then()。您需要在.then() 中复制以下代码;您可以通过将其放入自己的函数中来简化它。

    function maybeRepeat() {
      if (stop_condition) {
        finish();
      } else {
        calcStep1();
      }
    }
    
    function calcStep3() {
      // do more calculations
      pushToResults();
    
      if (some_condition) {
        getData().then(maybeRepeat);
      } else {
        maybeRepeat()
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-21
      • 2012-07-25
      • 1970-01-01
      • 2016-05-25
      • 2013-07-12
      • 1970-01-01
      • 2020-10-21
      • 2015-03-19
      相关资源
      最近更新 更多