I'm trying to learn by building a simple game with html and Js, using Nodejs and mongoose on the backend. It is like a grid where you can click to move around and you have to get to the treasure. When you click in the treasure tile, the backend gets the wincode from Mongodb and send it to the front.
miApp.allGames is an array where I store a "currentUserInfoMov" obcject with the info for every game currently being played, one for browser using local storage, that is working fine.
My problem is that movementsEmitter don't wait until it gets the code from Mongodb. In my console I can see the console.logs in this order:
1.you win!
2. Sent to front
3. Emitter finished
routerApi.post("/clicked", async (req, res) => {
try {
miApp.movementsEmitter.emit("playerWantToMove", req.body, grid);
const currentUserInfoMov = miApp.allGames.filter(x => x.Id == req.body.id)[0];
res.send(currentUserInfoMov);
console.log("Sent to Front");
} catch (error) {
console.log(error)
}
})
On the movementsEmitter:
movementsEmitter.on("playerWantToMove", async (tileClickedAndId, grid) => {
...more code here working fine...
if (playerDestiny == treasureTile) {
console.log("you win!");
const bottle = await Bottles.findById(BOTTLEID);
currentUserInfoMov.winCode = bottle.codeToWin;
TakeBottle();
console.log("Emitter finished");
}
}
CodePudding user response:
Based on your code, everything is happening as expected.
- you are emitting the
playerWantToMove
event - The
on
event handler is called => andconsole.log("you win!")
is called - You await a request to Bottles. This is an asynchronous request and gets moved to the job queue, until the call stack is empty.
- The code then the continues to execute your
.post
block => andconsole.log('sent to front')
is called - the call stack is now empty, so the code below the
awaited
line runs => and console.log(Emitter finished
) is called
So you need to reorder your code a bit. If you want to execute in a different order, just move the emit
to after res.send
. My guess though, is that takeBottle
updates the DB and therefore the response you are sending to the front end. You can try to await
the emitted event (if your event emitter allows that. await miApp.movementsEmitter.emit("playerWantToMove", ...)
. The other option is update the event handler to call res.send()
within that, after TakeBottle()
is called