TLDR: ¿debo usar async y await a través de una pila de llamadas complicada si la mayoría de las funciones no son realmente async ? ¿Existen patrones de programación alternativos?
Esta pregunta probablemente se trate más de patrones de diseño y arquitectura de software general que de un problema de sintaxis específico. Estoy escribiendo un algoritmo en node.js que es bastante complicado. El flujo del programa implica una llamada asíncrona inicial para obtener algunos datos y luego pasa a una serie de pasos de cálculo síncronos basados en los datos. Los pasos de cálculo son iterativos y, a medida que iteran, generan resultados. Pero ocasionalmente, si los cálculos cumplen ciertas condiciones, será necesario obtener más datos. Aquí hay una versión simplificada en forma de diagrama:
El bucle calcStep se ejecuta miles de veces sincrónicamente, impulsando los resultados. Pero ocasionalmente regresa a getData , y el programa debe esperar a que ingresen más datos antes de continuar nuevamente con el bucle calcStep .
Una versión reducida de lo anterior podría verse así en el código 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(); } } Donde pushToResults y finish también son funciones síncronas simples. Escribo las funciones calcStep aquí separadas porque en el código real, en realidad son métodos de clase de clases definidas en función de la separación de preocupaciones.
Surge el problema obvio de que si se cumple some_condition , y necesito esperar para obtener más datos antes de continuar con el ciclo calcStep , necesito usar la palabra clave await antes de llamar a getData en calcStep3 , lo que significa que calcStep3 debe llamarse async , y debemos await que también en calcStep2 , y en toda la cadena, incluso las funciones síncronas deben etiquetarse como async y await ed.
En este ejemplo simplificado, no sería tan ofensivo hacer eso. Pero en realidad, mi algoritmo es mucho más complicado, con una pila de llamadas mucho más profunda que involucra muchos métodos de clase, iteraciones, etc. ¿Existe una mejor manera de administrar las funciones en await en este tipo de escenario? ¿Otras herramientas que puedo usar, como generadores o emisores de eventos? Estoy abierto a soluciones simples o cambios de paradigma.
Si no desea sincronizar la función y async en la cadena, use .then() . Deberá duplicar el siguiente código dentro .then() ; puede simplificar esto poniéndolo en su propia función.
function maybeRepeat() { if (stop_condition) { finish(); } else { calcStep1(); } } function calcStep3() { // do more calculations pushToResults(); if (some_condition) { getData().then(maybeRepeat); } else { maybeRepeat() } }