如何在Discord.JS的SelectMenus中使用SQL查询结果添加选项?
问题原因
代码存在异步执行时序错误:sql.query是异步非阻塞操作,你传入回调函数处理查询结果的写法不会阻塞后续代码执行。程序发起SQL查询后会立刻往下执行添加固定选项、组装消息组件、发送回复的逻辑,等SQL结果返回、回调函数执行往菜单里加数据库选项的时候,消息已经发出去了,所以数据库里的选项根本不会出现在最终渲染的菜单里。
修复方法
把SQL查询逻辑改成async/await写法,强制等待查询结果返回、所有选项添加完成后,再执行后续发消息的逻辑,同时建议改用参数化查询避免SQL注入风险,修复后代码如下:
case "edit":{ const editrow = new MessageActionRow(); // 用?做占位符,避免直接拼接字符串带来的SQL注入风险 const query = `SELECT * FROM tickettypes WHERE guild_id = ?` const editmenu = new MessageSelectMenu() .setCustomId('editselect') .setPlaceholder('🔧 Select tickettype to edit') .addOptions([ { label: 'None', description: 'Empty', value: 'none', }, ]) // 等待SQL查询完成拿到结果后,再执行添加选项逻辑 const [result] = await sql.query(query, [interaction.guild.id]); console.log(result) result.forEach(item => { editmenu.addOptions([ { label: item.name, description: item.name, emoji: item.emoji, value: String(item.id), }, ]); }); editmenu.addOptions([ { label: '2 Test', description: 'Empty', value: 'test', }, ]) editrow.addComponents(editmenu); const editembed = new MessageEmbed() .setColor('YELLOW') .setTitle('Edit tickettype') .setAuthor({ name: interaction.user.username}) .setDescription('Select the tickettype you want to edit') await interaction.reply({ embeds: [editembed], components: [editrow], ephemeral: true}) } break;
注意:如果你使用的mysql驱动默认返回格式是结果直接作为query的返回值,就把
const [result]改成const result即可,根据你自己用的mysql包的返回格式调整。
如果你的环境不支持直接await sql.query,也可以把query逻辑包装成Promise实现等待效果,核心逻辑不变:必须等数据库结果返回、所有选项添加完成后,再发送带菜单的消息。
内容的提问来源于stack exchange,提问作者Felaxocraft
相关产品推荐
相关产品推荐

