Discord.js v14按钮嵌入交互失败求助:点击按钮显示交互失败
问题与解决:Discord.js v14 按钮切换Embed报错处理
问题说明
- 当前使用Discord.js v14,纠结是否要换回v13
- 目标:实现Slash命令,通过按钮切换Embed内容
- 异常:点击按钮后Discord提示“Interaction failed”,控制台无任何报错信息
原代码
const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js') module.exports = { data: new SlashCommandBuilder() .setName('testeando') .setDescription('test'), async execute(interaction, client) { const message = await interaction.deferReply({ fetchReply: true }); const embed = new EmbedBuilder() .setTitle('Test embed') .setDescription('Hola que ondaaaa'); const embed2 = new EmbedBuilder() .setTitle('Seeee') .setDescription('Hola que ondaaaa'); const row = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setLabel('Boton 1') .setStyle(ButtonStyle.Primary) .setCustomId('button1'), new ButtonBuilder() .setLabel('Boton 2') .setStyle(ButtonStyle.Secondary) .setCustomId('button2'), new ButtonBuilder() .setLabel('Boton 3') .setStyle(ButtonStyle.Success) .setCustomId('button3'), ) await interaction.editReply({ embeds: [embed], components: [row] }); const filter = i => i.customId === 'button1' || i.customId === 'button2'; const collector = interaction.channel.createMessageCollector({ filter, time: 15000 }); collector.on('collect', async i => { await i.deferUpdate(); if (i.customId === 'button1') { await interaction.editReply({ embeds: [embed], components: [row] }); } else if (i.customId === 'button2') { await interaction.editReply({ embeds: [embed2], components: [row] }); } collector.on('end', async () => { await interaction.editReply({ components: [] }); }); }); } }
错误分析
- 收集器类型错误:使用了
createMessageCollector(监听频道消息的收集器),而非createMessageComponentCollector(专门处理按钮、选择菜单等组件交互的收集器),导致按钮点击事件未被正确捕获。 - 事件绑定位置错误:
collector.on('end')被放在collect事件的回调内,每次收集到交互都会重复绑定end事件,引发逻辑混乱。 - 过滤器覆盖不全:过滤器只包含
button1和button2,但存在button3,点击后交互未被处理,触发Discord的“Interaction failed”提示。
修正后的代码
const { SlashCommandBuilder, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js') module.exports = { data: new SlashCommandBuilder() .setName('testeando') .setDescription('test'), async execute(interaction, client) { // 延迟回复,避免超时 await interaction.deferReply({ fetchReply: true }); // 定义两个切换用的Embed const embed1 = new EmbedBuilder() .setTitle('Test embed') .setDescription('Hola que ondaaaa'); const embed2 = new EmbedBuilder() .setTitle('Seeee') .setDescription('Hola que ondaaaa'); // 构建按钮行 const row = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setLabel('Boton 1') .setStyle(ButtonStyle.Primary) .setCustomId('button1'), new ButtonBuilder() .setLabel('Boton 2') .setStyle(ButtonStyle.Secondary) .setCustomId('button2'), new ButtonBuilder() .setLabel('Boton 3') .setStyle(ButtonStyle.Success) .setCustomId('button3'), ); // 发送初始回复 await interaction.editReply({ embeds: [embed1], components: [row] }); // 创建组件交互收集器,绑定到当前回复消息,仅允许发起命令的用户操作 const filter = i => ['button1', 'button2', 'button3'].includes(i.customId) && i.user.id === interaction.user.id; const collector = interaction.editReply.message.createMessageComponentCollector({ filter, time: 15000 }); // 处理收集到的交互 collector.on('collect', async i => { // 标记交互已接收,避免超时 await i.deferUpdate(); // 根据按钮ID切换Embed switch(i.customId) { case 'button1': await i.editReply({ embeds: [embed1], components: [row] }); break; case 'button2': await i.editReply({ embeds: [embed2], components: [row] }); break; case 'button3': // 可自定义button3的逻辑,比如切换其他Embed或提示 await i.editReply({ embeds: [embed1], components: [row] }); break; } }); // 收集器结束后移除按钮 collector.on('end', async () => { await interaction.editReply({ components: [] }); }); } }
版本建议
直接使用Discord.js v14即可,v13已停止官方维护,v14是当前稳定版本,拥有更完善的组件系统和API支持,后续更新和问题排查也更方便。
内容的提问来源于stack exchange,提问作者gTomii
相关产品推荐
相关产品推荐

