discord.js v13 按钮交互无理由触发Interaction Failed问题
问题触发原因
- 核心原因:Discord 交互机制有强制要求,所有按钮、斜杠命令等交互触发后,必须在3秒内向Discord返回响应确认,否则Discord会直接判定交互超时,弹出"Interaction Failed"提示。你当前的代码在按钮点击后只执行了消息编辑、消息删除操作,没有对交互本身做任何响应,哪怕业务逻辑执行成功,也会触发这个失败提示,且这类交互合规问题不会在控制台抛出JS运行错误。
- 附带隐性bug:
- 收集器
end事件里编辑消息的参数写错了,把复数形式的embeds写成了单数embed,会导致30秒超时后按钮禁用的逻辑失效。 - 用
global.msg全局变量存储消息引用的写法存在并发问题,多个用户同时触发抛硬币命令时,变量会被覆盖,导致操作错消息。
- 收集器
修复方案
- 在按钮交互的collect回调里,处理逻辑前先调用
i.deferUpdate(),这个方法会告知Discord交互已接收,不需要弹出额外回复,从根源解决交互失败提示。 - 修正
end事件里的参数拼写错误。 - 移除全局变量写法,直接使用消息发送后返回的消息对象做后续操作,同时把交互收集器绑定到对应抛硬币消息而非整个频道,避免误收集其他消息的按钮交互,解决并发冲突问题。
修复后的完整可运行代码:
const randomResult = Math.floor(Math.random() * 2) == 0 ? "Heads" : "Tails"; const embed = new MessageEmbed() .setTitle("Coin Flip") .setColor("YELLOW") .setDescription(` > ${randomResult}`) .setFooter({ text: `Requested by ${message.author.username}`, iconURL: message.author.displayAvatarURL(), }); const row = new MessageActionRow().addComponents( new MessageButton() .setCustomId("again") .setLabel("Throw Again") .setEmoji("🔁") .setStyle("PRIMARY"), new MessageButton() .setCustomId("delete") .setLabel("Delete") .setEmoji("♻") .setStyle("DANGER") ); message.channel.send({ embeds: [embed], components: [row] }).then(msg => { const iFilter = (i) => i.user.id === message.author.id; // 收集器绑定到当前发送的抛硬币消息,避免跨消息误触发 const collector = msg.createMessageComponentCollector({ filter: iFilter, time: 30000, }); collector.on("collect", async (i) => { // 核心修复:先响应交互,告知Discord已接收请求 await i.deferUpdate(); if (i.customId === "again") { const randomResult = Math.floor(Math.random() * 2) == 0 ? "Heads" : "Tails"; const newEmbed = new MessageEmbed() .setTitle("Coin Flip") .setColor("YELLOW") .setDescription(` > ${randomResult}`) .setFooter({ text: `Requested by ${message.author.username}`, iconURL: message.author.displayAvatarURL(), }); const newRow = new MessageActionRow().addComponents( new MessageButton() .setCustomId("again") .setLabel("Throw Again") .setEmoji("🔁") .setStyle("PRIMARY"), new MessageButton() .setCustomId("delete") .setLabel("Delete") .setEmoji("♻") .setStyle("DANGER") ); msg.edit({ embeds: [newEmbed], components: [newRow] }); } if (i.customId === "delete") { msg.delete(); } }) collector.on("end", async () => { // 修复拼写错误:将单数embed改为复数embeds const endEmbed = new MessageEmbed() .setTitle("Coin Flip") .setColor("YELLOW") .setDescription(` > 交互已超时`) .setFooter({ text: `Requested by ${message.author.username}`, iconURL: message.author.displayAvatarURL(), }); const endRow = new MessageActionRow().addComponents( new MessageButton() .setCustomId("ended") .setLabel("Coin Flip Ended") .setEmoji("❎") .setStyle("DANGER") .setDisabled(true), ); msg.edit({ embeds: [endEmbed], components: [endRow] }) }) })
内容的提问来源于stack exchange,提问作者Pooyan
相关产品推荐
相关产品推荐

