Skip to content Skip to sidebar Skip to footer

Javascript: Simple Async Issue

So I'm somewhat new to asynchronous JavaScript, and I can't figure out why the '.2's are logging before the '.1's. The only asynchronous method here is makePokemon() My goal is tha

Solution 1:

My understanding is that when using forEach() in the browser, the expectation is that the callback will execute synchronously.

You could however revise your code as follows (provided the parent function is declared async):

/* 
The following changes require the calling function to be async

async function foo() { *//* Express iteration with for..of to achieve desired behavior */for(const client of sender.room()) {
  
  const pokemon = awaitmakePokemon(client.getPokemon());
  client.setPokemon(pokemon);
  console.log('.1');

}

for(const client of sender.room()) {
  console.log('.2');
  client.emit('redirect', {
    yourPokemon: client.getPokemon(),
    theirPokemon: client.getOpponent().getPokemon()
  });
}

/* } */

Alternatively, as Patrick Roberts points out, you could express this logic in part with Promise.all(). One advantage with this approach is it allows multiple async tasks (ie makePokemon) to be dispatched at once rather than in a sequential fashion (as is the case above):

/* Map each client to a promise and execute all with Promise.all() */Promise.all(sender.room().map(async(client) => {
  const pokemon = awaitmakePokemon(client.getPokemon());
  client.setPokemon(pokemon);
  console.log('.1');
}))
/* If all prior promises are resolved, continue with next iteration */
.then(() => {

    for (const client of sender.room()) {
      console.log('.2');
      client.emit('redirect', {
        yourPokemon: client.getPokemon(),
        theirPokemon: client.getOpponent().getPokemon()
      });
    }
})

Solution 2:

Try waiting on all the promises:

const promises = sender.room().map(async (client) => {
                const pokemon = awaitmakePokemon(client.getPokemon());
                client.setPokemon(pokemon);
                console.log('.1');
            });
            awaitPromise.all(promises);
            sender.room().forEach(client => {
                console.log('.2');
                client.emit('redirect', {
                    yourPokemon: client.getPokemon(),
                    theirPokemon: client.getOpponent().getPokemon()
                });
            });

Solution 3:

forEach won't wait for each loop to finish, it simply fires off a bunch of promises. If you want to explicitly wait for all those promises to finish before the second loop starts you can use map followed by Promise.all. The map will return an array of promises. Promise.all will explicitly pause until all promises in the given array have resolved. Does something like this work?

// use `map` and capture each promise in a new arrayconst pokemonPromises = sender.room().map(async (client) => {
  const pokemon = awaitmakePokemon(client.getPokemon());
  client.setPokemon(pokemon);
  console.log('.1');
});

// explicitly wait for all promises to finish before continuing.awaitPromise.all(pokemonPromises);

// Continue with non async stuff
sender.room().forEach(client => {
  console.log('.2');
  client.emit('redirect', {
    yourPokemon: client.getPokemon(),
    theirPokemon: client.getOpponent().getPokemon()
  });
});

Post a Comment for "Javascript: Simple Async Issue"