Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

179
Views
Javascript recursive promise is firing the catch() twice, having a hard time following

I wrote a function in Discord.js v13 that expects user input. If the input is invalid, it needs to re-prompt them again, and the original promise should no longer be considered.

If the user takes longer than timeoutSeconds, then it throws an InputTimeout error.

What happens in practice, which I don't understand, is this:

  1. getResponse(...) is executed
  2. User is prompted for input
  3. User supplies invalid input
  4. User is informed of invalid input, and is re-prompted
  5. If no input is supplied, an InputTimeout error is thrown from the first request and the second request

What I wish to happen is:

  1. getResponse(...) is executed
  2. User is prompted for input
  3. User supplies invalid input
  4. User is informed of invalid input, and is re-prompted
  5. If no input is supplied, an InputTimeout error is thrown for the new request only

Here is what I think is happening... The second prompt is throwing the InputTimeout error which is causing the catch() handler from the first Promise to fire off. If that's true, then I am confused, because I thought if then() runs, then it's because no error was thrown. So why is catch() catching errors from the then() function? Should put catch() first, before then()? Is this an issue with the order I've chained the functions?

async getResponse(user, timeoutSeconds, channel = null) {
        if (channel == null) {
            const msg = await user.send(this.promptMessage);
            channel = msg.channel;
        }
        return await channel
            .awaitMessages({
                max: 1,
                time: timeoutSeconds * 1000,
                errors: ["time"],
            })
            .then(async (messages) => {
                if (messages.size == 1) {
                    const message = messages.values().next().value;
                    if (this.validator(message)) {
                        await user.send(this.successMessage);
                        return this.formatter(message);
                    } else {
                        await user.send(this.errorMessage);
                        await this.getResponse(
                            user,
                            timeoutSeconds,
                            channel
                        );
                    }
                }
            })
            .catch(async (e) => {
                console.error(e);
                await channel.send(this.timeoutMessage);
                throw new InputTimeout();
            });
    }
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

The issue was in fact the order of the .then() and .catch(). Since I was only concerned with catching errors from the awaitMessages() function, I should've chained it to that first, followed by the .then().

By putting catch() after then(), I was catching errors from my then() function.

Doh!

New solution, which also gets rid of .then() and .catch() as suggested by community:
try {
    let messages = await channel.awaitMessages({
        max: 1,
        time: timeoutSeconds * 1000,
        errors: ["time"],
    });
    messages = Array.from(messages.values());
    if (messages.length == 1) {
        const message = messages[0];
        if (message.author.bot) return;
        if (this.validator(message)) {
            await user.send(this.successMessage);
            return this.formatter(message);
        } else {
            await user.send(this.errorMessage);
            return this.getResponse( // note I removed "await" here to prevent nested errors
                user,
                timeoutSeconds,
                channel
            );
        }
    }
} catch (e) {
    console.error(e);
    await channel.send(this.timeoutMessage);
    throw new InputTimeout();
}
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!