javascript - diferir una llamada asíncrona en node hasta que todos los await del llamador terminen
TL;DR: ¿es posible decir "llamar a esa función una vez que todos los awaits en el contexto actual terminen" en JS/node?
Un ejemplo muy simplificado:
- un servicio orientado al frontend crea un nuevo usuario, luego realiza otra tarea asíncrona (
[1]) y devuelve - un servicio de usuario valida y guarda el nuevo usuario, luego dispara un evento (
[2]) que puede activar alguna otra lógica (no relacionada con la solicitud actual) - objetivo:
[1]siempre debe terminar antes de que los controladores de[2]comiencen a ejecutarse
class Service1 {
// say this is called from a controller / express route handler
async createUser(userData: NewUserData): Promise<UserWithAdditionalData> {
const user = await this.userSerivce.validateAndSaveUser(userData);
// [1] this is also async, and should finish before [2] handlers start running
const userWithData = await this.getSomeAdditionalData(user);
return userWithData;
}
}
class UserService {
async validateAndSaveUser(userData: NewUserData): Promise<User> {
const validatedData = await this.validateNewUserData(userData);
await this.dbService.saveNew(validatedData)
// [2] trigger an event/hook to be executed later
this.eventBus.onUserCreated();
}
}
La pregunta: ¿es posible implementar/reemplazar [2] de una manera que logre el objetivo mencionado? Preferiblemente de una mejor manera que programar el evento unos segundos en el futuro :D
En mi implementación actual, estoy usando una biblioteca de bus de eventos, que llama a los consumidores de eventos registrados cuando se desencadena un evento. Sin embargo, dado que probablemente solo esté agregando la función de retorno de llamada al bucle de eventos por debajo, es probable que se ejecute antes de [1] porque ambos simplemente se encolarán en el bucle de eventos. Por la misma razón, ocurre lo mismo si envuelvo los controladores en setTimeout(..., 0) o setImmediate. Lo que quiero lograr es que los controladores de eventos se ejecuten después de que todos los await del llamador hayan terminado.
// por favor, evitemos discutir si el patrón anterior es un buen diseño -- como la mayoría de las cosas, puede usarse tanto de manera buena como mala ;)