Discord.js导入报错:SyntaxError: Cannot use import statement outside a module
解决Discord机器人模态框数据传递与模块导入错误问题
问题描述
尝试将模态框处理文件(文件二)中的a1、a2、a3变量导入到按钮点击处理文件(文件一),用于生成Embed发送消息,但遇到SyntaxError: Cannot use import statement outside a module错误,尝试import和require两种方式均无效。相关代码如下:
文件一(GT1按钮处理)
module.exports = { data: { name: "GT1", }, async execute(interaction, client, message) { //const {a1, a2, a3} = require('./src/components/modals/GeneralTicket'); import {a1, a2, a3} from './src/components/modals/GeneralTicket.js' // const a1 = interaction.fields.getTextInputValue("a1"); // const a2 = interaction.fields.getTextInputValue("a2"); // const a3 = interaction.fields.getTextInputValue("a3"); const embed = new EmbedBuilder() .setColor(0x0099ff) .setTitle("General Support Ticket ") .setTimestamp() .addFields( { name: "IGN:", value: `${a1}` }, { name: "What is your Ticket related to:", value: `${a2}` }, { name: "Brief summary:", value: `${a3}` } ); createdChannel.send({ embeds: [embed], ephemeral: true, }); }, };
文件二(GeneralTicket模态框处理)
module.exports = { data: { name: `GeneralTicket` }, async execute(interaction, client, message) { client.on('interactionCreate', (modalSubmit) => { if (!modalSubmit.isModalSubmit()) return; const a1 = interaction.fields.getTextInputValue('a1'); const a2 = interaction.fields.getTextInputValue('a2'); const a3 = interaction.fields.getTextInputValue('a3'); const embed = new EmbedBuilder() .setColor(0x0099FF) .setTitle('General Support Ticket ') .setTimestamp() .addFields( { name: 'IGN:', value: `${a1}` }, { name: 'What is your Ticket related to:', value: `${a2}`}, { name: 'Brief summary:', value: `${a3}`}); const row = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId('GT1') .setLabel(`Submit`) .setStyle(ButtonStyle.Success) .setDisabled(false), ); modalSubmit.reply({ embeds: [embed] , ephemeral: true, components: [row], content: "To submit your ticket click `Submit` to cancel click `Dismiss Message`." }); }); }, };
尝试过的导入方式:
import {a1, a2, a3} from './src/components/modals/GeneralTicket.js' const { a1, a2, a3 } = require("./src/components/modals/GeneralTicket");
错误原因分析
- 模块系统冲突:当前代码使用CommonJS规范(
module.exports),却混用了ES模块的import语法,Node.js默认以CommonJS运行,直接使用import会触发语法错误。即使设置package.json的"type": "module"切换到ES模块,也不能再使用require,必须统一语法。 - 核心逻辑错误:文件二中的
a1、a2、a3是execute函数内部、interactionCreate回调里的局部变量,并非模块导出的常量,无论用哪种导入方式都无法获取这些运行时生成的临时数据。
解决方案
1. 统一模块语法
- 如果继续用CommonJS:所有文件使用
require和module.exports,禁止使用import/export。 - 如果切换到ES模块:在
package.json中添加"type": "module",所有文件改用import/export,不再使用require/module.exports。
2. 用缓存传递模态框数据
既然无法通过模块导入获取局部变量,我们可以将用户提交的模态框数据临时存储到客户端缓存,按钮点击时再从缓存中读取:
修改文件二(模态框处理)
module.exports = { data: { name: `GeneralTicket` }, async execute(interaction, client, message) { // 直接处理当前模态提交,无需重复监听interactionCreate if (!interaction.isModalSubmit()) return; const a1 = interaction.fields.getTextInputValue('a1'); const a2 = interaction.fields.getTextInputValue('a2'); const a3 = interaction.fields.getTextInputValue('a3'); // 初始化客户端缓存,用用户ID作为存储键 if (!client.ticketData) client.ticketData = new Map(); client.ticketData.set(interaction.user.id, {a1, a2, a3}); const embed = new EmbedBuilder() .setColor(0x0099FF) .setTitle('General Support Ticket ') .setTimestamp() .addFields( { name: 'IGN:', value: `${a1}` }, { name: 'What is your Ticket related to:', value: `${a2}`}, { name: 'Brief summary:', value: `${a3}`}); const row = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId('GT1') .setLabel(`Submit`) .setStyle(ButtonStyle.Success) .setDisabled(false), ); await interaction.reply({ embeds: [embed], ephemeral: true, components: [row], content: "点击「Submit」提交工单,点击「Dismiss Message」取消。" }); }, };
修改文件一(按钮处理)
module.exports = { data: { name: "GT1", }, async execute(interaction, client, message) { // 从客户端缓存读取当前用户的工单数据 const ticketData = client.ticketData?.get(interaction.user.id); if (!ticketData) { return interaction.reply({ content: "未找到你的工单数据,请重新提交模态框。", ephemeral: true }); } const {a1, a2, a3} = ticketData; const embed = new EmbedBuilder() .setColor(0x0099ff) .setTitle("General Support Ticket ") .setTimestamp() .addFields( { name: "IGN:", value: `${a1}` }, { name: "What is your Ticket related to:", value: `${a2}` }, { name: "Brief summary:", value: `${a3}` } ); // 发送工单到目标频道 await createdChannel.send({ embeds: [embed] }); // 回复用户提交成功 await interaction.reply({ content: "工单已成功提交!", ephemeral: true }); // 删除缓存释放内存 client.ticketData.delete(interaction.user.id); }, };
3. 额外优化点
- 不要在
execute函数内重复监听interactionCreate,应在机器人主文件统一注册事件,每个交互处理函数仅处理对应类型的交互(如模态提交、按钮点击)。 - 如果需要持久化数据,可以用数据库替代客户端缓存,避免机器人重启后数据丢失。
内容的提问来源于stack exchange,提问作者Icebreaker
相关产品推荐
相关产品推荐

