Javascript 递归承诺触发 catch() 两次,很难跟进

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

我在 Discord.js v13 中编写了一个需要用户输入的函数。如果输入无效,需要重新提示一遍,原来的promise应该不再考虑了。

如果用户花费的时间超过 timeoutSeconds,则会抛出 InputTimeout 错误。

实践中发生了什么,我不明白,是这样的:

  1. getResponse(...) 被执行
  2. 提示用户输入
  3. 用户提供了无效输入
  4. 用户被告知输入无效,并被重新提示
  5. 如果没有提供输入,第一个请求会抛出一个InputTimeout错误 第二个 请求

我希望发生的是:

  1. getResponse(...) 被执行
  2. 提示用户输入
  3. 用户提供了无效输入
  4. 用户被告知输入无效,并被重新提示
  5. 如果未提供任何输入,则仅针对新请求抛出 InputTimeout 错误

这是我认为正在发生的事情...第二个提示抛出 InputTimeout 错误,导致第一个 Promise 中的 catch() 处理程序被触发。如果那是真的,那么我很困惑,因为我认为如果 then() 运行,那是因为没有抛出错误。那么为什么 catch()then() 函数中捕获错误呢?应该把catch()放在第一位,在then()之前吗?这是我链接函数的顺序的问题吗?

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();
            });
    }

问题实际上是 .then().catch() 的顺序。因为我只关心捕获来自 awaitMessages() 函数的错误,所以我应该首先将它链接到那个,然后是 .then().

通过将 catch() 放在 then() 之后,我从 then() 函数中捕获了错误。

哎呀!

新解决方案,也按照社区的建议删除了 .then().catch()
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();
}