为什么这个获取错误处理不起作用?

Why won't this fetch error handling work?

我有一个使用 discord.js 的 Discord 机器人。由于我实施了斜杠命令,如果服务器在从中获取文件时出现故障,它会使我的机器人崩溃。我已经尝试了很多事情,但我似乎无法弄清楚如何正确地捕获错误。

这是我的命令代码:

<!-- language: js -->
const { SlashCommandBuilder } = require('@discordjs/builders');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('fetchtest')
        .setDescription('Fetch GTA:SA files.')
        .addSubcommand(gta3Cmd =>
            gta3Cmd
                .setName('gta3')
                .setDescription('Fetch files from gta3.img')
                .addStringOption(option => option.setName('file').setRequired(true).setDescription('File to fetch from database.')))
        .addSubcommand(playerCmd =>
            playerCmd
                .setName('player')
                .setDescription('Fetch files from player.img')
                .addStringOption(option => option.setName('file').setRequired(true).setDescription('File to fetch from database.'))),

    async execute(interaction) {
        let imageFile;
        if (interaction.options.getSubcommand() === 'gta3') {
            imageFile = 'gta3';
        }
        else if (interaction.options.getSubcommand() === 'player') {
            imageFile = 'player';
        }

        await interaction.client.fetch(`${interaction.client.config.gtaApiServer}/api/v1/gta/sa/${imageFile}?title=${interaction.options.getString('file')}`)
            .then((fetchGameFile) => {
                if (fetchGameFile.ok) {
                    const gameFileData = fetchGameFile.json();
                    let hasReturned = false;

                    if (gameFileData[0].urlDFF != undefined) {
                        interaction.reply({
                            files: [
                                gameFileData[0].urlDFF,
                            ],
                        });
                        hasReturned = true;
                    }

                    if (hasReturned === true && gameFileData[0].urlTXD != undefined) {
                        interaction.followUp({
                            files: [
                                gameFileData[0].urlTXD,
                            ],
                        });
                    }

                    else if (hasReturned === false && gameFileData[0].urlTXD != undefined) {
                        interaction.reply({
                            files: [
                                gameFileData[0].urlTXD,
                            ],
                        });
                    }

                    else {
                        interaction.reply(`File with name ${interaction.options.getString('file')} not found.`);
                        return;
                    }
                }
                else {
                    return interaction.reply('Server is down');
                }
            });
    },
};

这会触发以下错误:

FetchError: request to http://serverip/api/v1/gta/sa/gta3?title=fam2 failed, reason: connect ETIMEDOUT serverip
    at ClientRequest.<anonymous> (C:\Projects\klochon\node_modules\node-fetch\lib\index.js:1461:11)
    at ClientRequest.emit (node:events:394:28)
    at Socket.socketErrorListener (node:_http_client:447:9)
    at Socket.emit (node:events:394:28)
    at emitErrorNT (node:internal/streams/destroy:157:8)
    at emitErrorCloseNT (node:internal/streams/destroy:122:3)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) {
  type: 'system',
  errno: 'ETIMEDOUT',
  code: 'ETIMEDOUT'
}

C:\Projects\klochon\node_modules\discord.js\src\rest\RequestHandler.js:298
      throw new DiscordAPIError(data, res.status, request);
            ^

DiscordAPIError: Unknown interaction
    at RequestHandler.execute (C:\Projects\klochon\node_modules\discord.js\src\rest\RequestHandler.js:298:13)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async RequestHandler.push (C:\Projects\klochon\node_modules\discord.js\src\rest\RequestHandler.js:50:14)
    at async CommandInteraction.reply (C:\Projects\klochon\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:99:5)
    at async Client.<anonymous> (C:\Projects\klochon\index.js:51:3) {
  method: 'post',
  path: '/interactions/881934786988499044/aW50ZXJhY3Rpb246ODgxOTM0Nzg2OTg4NDk5MDQ0OjRvUWMzeHVnQzl2QjlIM2tqRVZpSENmTTlkQ1FWYUE1dHFac1JaTWdTcjE2UWZZaXFKYWk2eXppZkM5cE9GcW5HQUdLNnN4UDZXcU5JR2JCelljQUxDdHNJUktpUzdwRmZzYnRzcVZKNFIzczB6MDRHVXlGYndtb0J0a2RzSDZj/callback',
  code: 10062,
  httpStatus: 404,
  requestData: {
    json: {
      type: 4,
      data: {
        content: 'There was an error while executing this command!',
        tts: false,
        nonce: undefined,
        embeds: undefined,
        components: undefined,
        username: undefined,
        avatar_url: undefined,
        allowed_mentions: undefined,
        flags: 64,
        message_reference: undefined,
        attachments: undefined,
        sticker_ids: undefined
      }
    },
    files: []
  }
}

我已经阅读了有关如何在抓取时捕获错误的示例,但似乎没有任何效果。有时它会停止崩溃,但机器人不会回复,或者我得不到 console.log 回复。如果有任何提示,我将不胜感激。

可能是一种解决方法,并不能解决您实际的“问题”,但您可以在整个 command/your 获取部分周围放置一个 try-catch 块。

您的 fetch 可能会返回一个因服务器停机而被拒绝的 Promise。由于您使用的是 await,这会导致 JavaScript 错误。

如果您想使用 async/await 处理被拒绝的 Promise,那么您需要使用 try/catch 块。

try {
  await fetch(...)
} catch(e) {
  // e is the rejected promise reason, usually an error
}

有关详细信息,请参阅 MDN's "Promise rejection"