TL;DR: is it possible to say "call that function once all awaits in the current context finish" in JS/node?
A very simplified example:
- a frontend-facing service creates a new user, then does another async task (
[1]) and returns - a user service validates & saves the new user, then fires an event (
[2]) that can trigger some other logic (unrelated to the current request) - goal:
[1]should always finish before handlers for[2]start running
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();
}
}
The question: is it possible to implement/replace [2] in a way to achieve the mentioned goal? Preferably in a better way than scheduling the event a few seconds in the future :D
In my current implementation, I'm using an event bus library, that calls registered event consumers when an event is triggered. However, since it's probably just pushing the callback onto the event loop under the hood, it's likely to be executed before [1] because both will just be queued onto the event loop. For the same reason, the same happens if I wrap the handlers in setTimeout(..., 0) or setImmediate. What I want to achieve, is that the event handlers should be fired after all the awaits from the caller are finished.
// please let's avoid discussing if the pattern above is a good design -- like most things, it can be used both in good and bad ways ;)