【发布时间】:2021-11-21 18:02:18
【问题描述】:
TLDR:如果大多数函数实际上不是async,我是否必须通过复杂的调用堆栈使用async 和await?有替代的编程模式吗?
上下文
这个问题可能更多地是关于设计模式和整体软件架构,而不是特定的语法问题。我正在用 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();
}
}
其中pushToResults 和finish 也是简单的同步函数。我在这里写的calcStep 函数是分开的,因为在实际代码中,它们实际上是基于关注点分离定义的类的类方法。
问题
出现了明显的问题,如果遇到some_condition,我需要等待获取更多数据才能继续calcStep循环,我需要在calcStep3中调用getData之前使用await关键字,这意味着calcStep3必须被称为async,我们必须在calcStep2中也必须await,并且一直到链上,即使是同步函数也必须标记为async和awaited。
在这个简化的例子中,这样做不会太冒犯。但实际上,我的算法要复杂得多,调用堆栈要深得多,涉及许多类方法、迭代等。在这种情况下,有没有更好的方法来管理awaiting 函数?我可以使用的其他工具,例如生成器或事件发射器?我愿意接受简单的解决方案或范式转变。
【问题讨论】:
标签: javascript node.js asynchronous design-patterns callstack