ButtonInteraction.awaitModalSubmit()多次注册引发重复提交问题
问题描述
我有一个附带Embed和按钮组件的Interaction,点击任意按钮会弹出Modal。但出现异常:点击按钮后关闭Modal,再次点击按钮并提交内容时,会被记录为两次提交;若重复打开关闭Modal6次后再提交,会被记录7次提交。尝试使用.deferReply()反而引发更多错误,多数搜索到的解决方案均无效。
相关代码
const collector = res.createMessageComponentCollector( { componentType: ComponentType.Button, // 1,000ms = 1s / 60,000ms => 1min time: 1000*60 } ); collector.on('collect', async i => new Promise(async (res, reject) => { const modal = createTicketModal(i.customId); i.showModal(modal); await i.awaitModalSubmit({ time: 60000, filter: (modalSubmitI) => { return modalSubmitI.customId === 'input-ticket-info'; } }) .then((modalSubmitI) => { modalSubmitI.channel.send('modal submitted') }).catch(error => { console.error(error) return null }) }));
问题原因与修复方案
问题根源
每次点击按钮时,都会创建一个新的awaitModalSubmit监听,但关闭Modal时这些监听并未被清除。多次打开关闭Modal后,监听会累积,导致后续提交时所有未清理的监听同时触发,出现多次提交记录。
修改后的代码
const collector = res.createMessageComponentCollector({ componentType: ComponentType.Button, time: 1000 * 60 // 1分钟 }); collector.on('collect', async (i) => { // 避免重复处理同一按钮交互 if (i.deferred || i.replied) return; const modal = createTicketModal(i.customId); await i.showModal(modal); try { const modalSubmitI = await i.awaitModalSubmit({ time: 60000, filter: (modalSubmitI) => modalSubmitI.customId === 'input-ticket-info' }); // 正确响应Modal提交交互,避免超时 await modalSubmitI.deferReply({ ephemeral: true }); await modalSubmitI.channel.send('modal submitted'); await modalSubmitI.editReply('提交已处理'); } catch (error) { // 仅记录异常错误,忽略正常的关闭/超时情况 if (error.code !== 'INTERACTION_COLLECTOR_ERROR') { console.error(error); } } });
关键修复点
- 移除冗余的Promise嵌套,简化逻辑结构;
- 增加按钮交互状态判断,防止重复处理;
- 处理Modal提交时,规范使用
deferReply和editReply响应交互,避免Discord的超时错误; - 过滤掉
awaitModalSubmit正常的关闭/超时错误,减少控制台无效报错。
另外需确认createTicketModal生成的Modal的customId确实为input-ticket-info,否则过滤条件会失效。
内容的提问来源于stack exchange,提问作者Giorno Giobama
相关产品推荐
相关产品推荐

