0

I'm trying to implement a function inside a loop that waits for the client's reply.

It only goes to the next iteration after the client replied and it runs exactly three times.

I'm running into the issue that whenever the function is run, it executes all three "promises" without waiting for the previous one to finish first.

How would I go about solving this? Thank you.

module.exports = {
    name: 'tournamentwinners',
    description: 'Prepare a pretty message to showcase last tournament\'s winners',
    aliases: ['trwin', 'tournwin'],
    execute(client, message, args) {
        const teamSize = args[0].toLowerCase();
        const firstPlaceTeamMembers = new Array(teamSize);
        const secondPlaceTeamMembers = new Array(teamSize);
        const thirdPlaceTeamMembers = new Array(teamSize);

        const filter = m => m.author.id === message.author.id;
        for (let i = 0; i < 3; i++) {
            message.channel.send(`Which team finished in #${i + 1}? (tag all ${teamSize} people)`).then(() => {
                message.channel.awaitMessages(filter, {
                    max: 1,
                    time: 30000,
                    errors: ['time'],
                })
                    .then(msg => {
                        msg = msg.first();
                        const members = msg.mentions.members.values();

                        for(let j = 0; members.hasNext(); j++) {
                            if(i == 0) {
                                firstPlaceTeamMembers[j] = members.next().value;
                            } else if(i == 1) {
                                secondPlaceTeamMembers[j] = members.next().value;
                            } else {
                                thirdPlaceTeamMembers[j] = members.next().value;
                            }
                        }

                    })
                    .catch(collected => {
                        message.channel.send('Something messed up...');
                    });
            });
        }
    },
};
Asfourhundred
  • 3,003
  • 2
  • 13
  • 18

2 Answers2

0

Inside the for loop, you are triggering all the promises immediately after one another. Instead you should use the await keyword. See: Resolve promises one after another (i.e. in sequence)?

a5af
  • 2,514
  • 2
  • 14
  • 13
0

To do this with then() syntax, it's a little clumsier, but the idea is to build a chain of promises, attaching each to the one prior.

Follow this form:

// this function returns a promise to do one iteration of message work
function promiseGeneratingFunction(client, message, args) {
  // it's important to "return" the promise here
  return message.channel.send(/* etc */).then(msg => {
    /* etc */
  })
}

module.exports = {
  name: 'tournamentwinners',
  description: 'Prepare a pretty message to showcase last tournament\'s winners',
  aliases: ['trwin', 'tournwin'],
  execute(client, message, args) {
    let promiseChain = Promise.resolve();
    [ 0, 1, 2].forEach(() => {
      promiseChain = promiseChain.then(() => promiseGeneratingFunction(client, message, args))
    })
    return promiseChain.catch(err => { /* handle error */ })
  }
}

This can be simplified a bit by using the async/await syntax...

// this function returns a promise to do one iteration of message work
async function promiseGeneratingFunction(client, message, args) {
  // it's important to "return" the promise here
  return message.channel.send(/* etc */).then(msg => {
    /* etc */
  })
}

module.exports = {
  name: 'tournamentwinners',
  description: 'Prepare a pretty message to showcase last tournament\'s winners',
  aliases: ['trwin', 'tournwin'],
  execute(client, message, args) {
    try {
      [ 0, 1, 2].forEach(() => {
        await promiseGeneratingFunction(client, message, args);
      })
    } catch (err) { /* handle error */ })
  }
}
danh
  • 62,181
  • 10
  • 95
  • 136