gclark18
gclark18

Reputation: 725

Discord.js, async and await

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

Upvotes: 3

Views: 8398

Answers (1)

Ivan Rubinson
Ivan Rubinson

Reputation: 3329

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

Upvotes: 2

Related Questions