2
const getNumberOfQuestions = async () => {
    await this.channel.send('How many questions should I ask? (1-10)')
        .then(async message => {
            await this.channel.awaitMessages(message => message.author.id === this.owner && !isNaN(parseInt(message.content)),  { max: 1, time: 15000 })
                .then(collected => {
                    this.channel.send(`You asked for ${collected.first().content} questions.`);
                    return parseInt(collected.first().content);
                })
                .catch(collected => {
                    this.channel.send('You did not tell me how many questions you wanted. Ending the quiz.');
                });
        });
};

const getDifficulty = async () => {
    await this.channel.send('What difficulty would you like: easy, medium, hard?')
        .then(message => {
            this.channel.awaitMessages(message => message.author.id === this.owner && ['easy', 'medium', 'hard'].includes(message.content.toLocaleLowerCase()),  { max: 1, time: 15000 })
                .then(collected => {
                    this.channel.send(`You asked for ${collected.first().content} difficulty.`);
                    return collected.first().content;
                })
                .catch(collected => {
                    this.channel.send('You did not tell which difficulty you wanted. Ending the quiz.');
                });
        });

};
getNumberOfQuestions();
getDifficulty();

With the above code, I do not want the execution to continue past this function when it is called. I clearly do not understand promises and await can some one help me?

.send and .awaitMessages both return a promise

gclark18
  • 659
  • 6
  • 23
  • 2
    You can't have control on the execution flow. With `async-await` the only thing you can be sure about is that the code **after** an `await` won't be executed till the result of the awaited expression is not returned – dc_Bita98 Aug 15 '20 at 19:12
  • 1
    What exactly do you mean by "I do not want the execution to continue past this function when it is called"? – Ivan Rubinson Aug 15 '20 at 19:25
  • Ivan, This function asks the user to select a number of questions. I then have more functions that ask other questions to the user that require input. Currently, all the question fire at the same time. I want to somehow wait until the first one is done, then ask the next one etc. – gclark18 Aug 15 '20 at 19:26
  • 1
    What you may need in that case is known as a lock, which would prevent multiple flows from entering the same critical section at the same time. https://stackoverflow.com/questions/34524/what-is-a-mutex – Ivan Rubinson Aug 15 '20 at 19:27
  • 1
    We don't see the code that asks the other questions which you'd like to make serial instead of parallel. Please make a [mcve](https://stackoverflow.com/help/minimal-reproducible-example)? – Ivan Rubinson Aug 15 '20 at 19:29
  • Ivan, I have updated the code. – gclark18 Aug 15 '20 at 19:34

1 Answers1

1

First let me refactor your two procedures that have a mix of promises and async/await so that they have just equivalent async/await.

const getNumberOfQuestions = async () => {
    const message = await this.channel.send('How many questions should I ask? (1-10)');
    try {
        const collected = await this.channel.awaitMessages(message => message.author.id === this.owner && !isNaN(parseInt(message.content)),  { max: 1, time: 15000 });
        this.channel.send(`You asked for ${collected.first().content} questions.`);
        return parseInt(collected.first().content);
    } catch(collected) {
        this.channel.send('You did not tell me how many questions you wanted. Ending the quiz.');
    }
};

const getDifficulty = async () => {
    const message = await this.channel.send('What difficulty would you like: easy, medium, hard?');
    try {
        const collected = await this.channel.awaitMessages(message => message.author.id === this.owner && ['easy', 'medium', 'hard'].includes(message.content.toLocaleLowerCase()),  { max: 1, time: 15000 });
        this.channel.send(`You asked for ${collected.first().content} difficulty.`);
        return collected.first().content;
    } catch(collected) {
        this.channel.send('You did not tell which difficulty you wanted. Ending the quiz.');
    }
};

As you can see, awaiting on a promise is like treating what's after it as inside a then, where the resolved value is what's returned by the awaited expression. The rejection (.catch()) of the promise is translated to an exception which can be try{...}catch{...}ed.

Knowing this, what you're doing by calling

getNumberOfQuestions();
getDifficulty();

is calling both functions asynchronously - without waiting for the promises returned to settle. What you may want to do instead is to await the first's end before invoking the second. Like so:

await getNumberOfQuestions();
await getDifficulty();

However, the await keyword makes sense only in an async function, so you can do it like so:

(async()=>{
    await getNumberOfQuestions();
    await getDifficulty();
})();

More about async functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

Ivan Rubinson
  • 3,001
  • 4
  • 19
  • 48