You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.js模态框取消未终止等待引发重复回复报错求助

模态框交互问题解决思路

核心问题分析

  1. 点击模态框取消按钮时,awaitModalSubmit仅监听提交事件,不会响应取消操作,导致收集器持续等待超时;期间用户重复执行命令会创建多个并行收集器。
  2. 多个活跃收集器同时监听同一用户的模态提交,会触发多次回复操作,进而引发Interaction has already been acknowledged错误。

具体解决方案

1. 监听取消事件,主动终止收集器

改用MessageComponentCollector替代awaitModalSubmit,同时监听模态框取消事件,主动停止收集器,避免无意义等待:

const { ComponentType } = require('discord.js');

// 命令执行逻辑内
await interaction.showModal(submissionValidateModal);

const collector = interaction.channel.createMessageComponentCollector({
  filter: i => i.user.id === interaction.user.id,
  time: 60000,
  componentType: ComponentType.Modal
});

// 处理模态框提交
collector.on('collect', async i => {
  if (!i.replied && !i.deferred) {
    await i.reply({ embeds: [requestedSentEmbed], ephemeral: true });
  }
  collector.stop();
});

// 处理收集器结束(包括超时、取消)
collector.on('end', (collected, reason) => {
  if (reason === 'userCancel' && !interaction.replied && !interaction.deferred) {
    interaction.followUp({ content: '操作已取消', ephemeral: true });
  }
});

// 监听模态框取消事件,触发收集器停止
interaction.on('modalCancelled', () => {
  collector.stop('userCancel');
});

2. 限制用户同时存在活跃模态会话

用全局Map记录当前有活跃模态框的用户,重复执行命令时直接拦截:

const { ComponentType } = require('discord.js');
// 全局/模块级变量,存储用户ID与对应收集器的映射
const activeModals = new Map();

// 命令执行逻辑内
if (activeModals.has(interaction.user.id)) {
  return interaction.reply({ content: '你有一个正在进行的操作,请先完成或取消它', ephemeral: true });
}

await interaction.showModal(submissionValidateModal);

const collector = interaction.channel.createMessageComponentCollector({
  filter: i => i.user.id === interaction.user.id,
  time: 60000,
  componentType: ComponentType.Modal
});

activeModals.set(interaction.user.id, collector);

collector.on('collect', async i => {
  if (!i.replied && !i.deferred) {
    await i.reply({ embeds: [requestedSentEmbed], ephemeral: true });
  }
  collector.stop();
});

collector.on('end', () => {
  activeModals.delete(interaction.user.id);
});

interaction.on('modalCancelled', () => {
  collector.stop('userCancel');
});

3. 应急处理:避免重复回复交互

在回复前检查交互状态,确保每个交互只被回复一次,即使出现多个收集器触发的情况:

// 原代码中的回复部分修改为
if (modalReply && !modalReply.replied && !modalReply.deferred) {
  await modalReply.reply({ embeds: [requestedSentEmbed], ephemeral: true });
}

内容的提问来源于stack exchange,提问作者Bobosky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 06:35:13