Discord.js V14按钮交互异常:首次点击失败、Bot偶发崩溃
Discord.js V14 机器人按钮交互异常问题
我基于Discord.js V14开发了一款Discord机器人,创建了文本触发指令:用户发送test后,机器人会发送带按钮的消息,点击按钮时消息需更新为“button was clicked”。但实际运行中出现以下问题:
- 按钮可正常发送,但首次点击提示“interaction failed”,二次点击才正常生效
- 再次执行指令时,机器人有时直接崩溃,有时发送按钮后崩溃
原代码
client.on('messageCreate', (message) => { if (message.author.bot) return; if (message.content === 'test') { let row = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId('test') .setLabel('testing') .setStyle(ButtonStyle.Primary), ); message.channel.send({ content: 'hey there!', components: [row] }); } client.on('interactionCreate', (interaction) => { if (!interaction.isButton()) { message.channel.send('hello gringo'); }; if (interaction.customId) console.log(interaction); const filter = i => i.customId === 'test' && i.user.id === '877466540679786536'; const collector = interaction.channel.createMessageComponentCollector({ filter, time: 15000 }); collector.on('collect', async i => { await i.update({ content: 'Button was clicked!', components: [] }); }); collector.on('end', collected => console.log(`Collected ${collected.size} items`)); }) });
报错信息
rawError: { message: 'Interaction has already been acknowledged.', code: 40060 }, code: 40060, status: 400, method: 'POST', url: 'https://discord.com/api/v10/interactions/1064212307045003315/aW50ZXJhY3Rpb246MTA2NDIxMjMwNzA0NTAwMzMxNTpJOGxpUEttZ2U3ZERIaW9iRXg4VkxiN2ZpREZJN2RRV2d6WW9uMUE3dXR2RFpNckI4SnliMEpCZGFEWm9qUVg0R2duS3ZTWk1UVkMyM015SWlKYk94cjU0Q3FWMVhCUFA5UDQzeWJVTzZPU09YNmZBR2NwS3MxZjRXeGgzOVAzSA/callback' }
问题根源
- 重复绑定
interactionCreate事件:每次触发messageCreate(比如用户发test),都会新增一个interactionCreate监听器。触发次数越多,监听器堆积越多,同一个交互会被多次处理,直接引发“交互已被响应”的错误,甚至导致机器人崩溃。 - 错误的非按钮交互处理:当收到非按钮交互时,直接调用
message.channel.send,这里的message是上一次messageCreate的上下文,会导致逻辑混乱,且未对交互做正确响应。 - 冗余的消息组件收集器:仅需处理单次按钮点击,不需要使用收集器,收集器会和直接处理逻辑冲突,增加不必要的复杂度。
修复后的代码
const { Client, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); const client = new Client({ intents: [/* 请确保启用必要的权限,如Guilds、GuildMessages、MessageContent */] }); // 仅绑定一次interactionCreate事件,放在messageCreate外部 client.on('interactionCreate', async (interaction) => { // 非按钮交互直接返回,避免无效处理 if (!interaction.isButton()) return; // 校验按钮ID和用户ID if (interaction.customId === 'test' && interaction.user.id === '877466540679786536') { try { // 更新消息内容并移除按钮 await interaction.update({ content: 'Button was clicked!', components: [] }); } catch (error) { console.error('按钮交互处理失败:', error); } } }); client.on('messageCreate', (message) => { if (message.author.bot) return; if (message.content === 'test') { const row = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId('test') .setLabel('testing') .setStyle(ButtonStyle.Primary) ); // 增加错误捕获,防止发送消息失败导致崩溃 message.channel.send({ content: 'hey there!', components: [row] }).catch(error => console.error('消息发送失败:', error)); } }); // 登录机器人 client.login('你的机器人令牌');
核心修复点
- 将
interactionCreate监听器移至messageCreate外部,确保仅绑定一次,避免重复处理交互 - 移除冗余的消息组件收集器,直接在
interactionCreate中处理按钮点击逻辑 - 修正非按钮交互的处理逻辑,直接返回而非错误发送消息
- 添加错误捕获,避免异常导致机器人崩溃
内容的提问来源于stack exchange,提问作者GoMidas69
相关产品推荐
相关产品推荐

