在算法调用堆栈中管理同步和异步函数
Managing sync and async functions in an algorithm call stack
TLDR:如果 大多数 函数实际上不是 [=11],我必须通过复杂的调用堆栈使用 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
函数是分开的,因为在实际代码中,它们实际上是 class 方法,来自 class 基于关注点分离定义的方法。
问题
明显的问题出现了,如果满足some_condition
,我需要等待获取更多数据才能继续calcStep
循环,我需要在之前使用await
关键字在 calcStep3
中调用 getData
,这意味着 calcStep3
必须被调用 async
,我们也必须 await
在 calcStep2
中调用,并且所有在链条上,即使是同步函数也必须标记为 async
和 await
ed.
在这个简化的示例中,这样做不会太令人反感。但实际上,我的算法要复杂得多,调用堆栈更深,涉及许多 class 方法、迭代等。在这种情况下,是否有更好的方法来管理 await
ing 函数?我可以使用的其他工具,如生成器或事件发射器?我愿意接受简单的解决方案或范式转变。
如果您不想创建函数 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()
}
}
TLDR:如果 大多数 函数实际上不是 [=11],我必须通过复杂的调用堆栈使用 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
函数是分开的,因为在实际代码中,它们实际上是 class 方法,来自 class 基于关注点分离定义的方法。
问题
明显的问题出现了,如果满足some_condition
,我需要等待获取更多数据才能继续calcStep
循环,我需要在之前使用await
关键字在 calcStep3
中调用 getData
,这意味着 calcStep3
必须被调用 async
,我们也必须 await
在 calcStep2
中调用,并且所有在链条上,即使是同步函数也必须标记为 async
和 await
ed.
在这个简化的示例中,这样做不会太令人反感。但实际上,我的算法要复杂得多,调用堆栈更深,涉及许多 class 方法、迭代等。在这种情况下,是否有更好的方法来管理 await
ing 函数?我可以使用的其他工具,如生成器或事件发射器?我愿意接受简单的解决方案或范式转变。
如果您不想创建函数 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()
}
}