async await in loops

I have this code, but I don't understand why this all gets printed right after each other, where I would expect that the rl.question call gives me a prompt in terminal which waits for input. useful information is that before this piece is run, there is another part that also uses the rl.question where it actually waits for that user input in the terminal (and then uses that as expected in the callback)
for (let round = 1; round <= this.GAME_ROUNDS; round++) {
for (let player of this.players) {
this.startTurn();
console.log(`starting turn for player in round ${round}`);
console.log("" + player);

rl.question("What do you want to do now? (F) Forge / (H) Heroic feat",
(answer) => {console.log(`excellent choice that ${answer}, but this isn't implemented yet`)});
}
}
for (let round = 1; round <= this.GAME_ROUNDS; round++) {
for (let player of this.players) {
this.startTurn();
console.log(`starting turn for player in round ${round}`);
console.log("" + player);

rl.question("What do you want to do now? (F) Forge / (H) Heroic feat",
(answer) => {console.log(`excellent choice that ${answer}, but this isn't implemented yet`)});
}
}
2 Replies
denertog
denertog2y ago
okay, I've already narrowed it down a bit, however I still don't understand why it executes playTurn twice before waiting for input (during playTurn)
for (let player of this.players) {
await this.playTurn(player, round);
}
for (let player of this.players) {
await this.playTurn(player, round);
}
13eck
13eck2y ago
That's because for (and for...of, and Array.forEach() are all synchronous loops. If you want an async loop you need to use an async loop structure. Assuming that If this.players is an array of promises, you can use Promise.allSettled(this.players) and you'll get back an array with the results of all the async code in the players array. Add a .then() to handle the results. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled Otherwise, if you prefer for...of you can use the async version for await...of which will await the result of each value before continuing on. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of Promise.allSettled() is great for when you don't care about the order of when things are done, it'll resolve when all the promises are done. for await...of actually goes through each item one at a time, awaiting the response from one before moving on to the next. The first is truly asynchronous (as it doesn't care what order, it just cares that it all gets done) while the second is more linear since it waits on one before moving on to the next.
Want results from more Discord servers?
Add your server