如何在MessageComponentCollector中正确获取变量值?async/await相关变量未定义问题排查
问题排查与解决方案:Discord.js组件收集器中
approvalChoice始终为undefined的原因及修复 问题原因分析
你的代码里有两个核心问题导致approvalChoice一直处于undefined状态:
错误地对事件监听器使用
awaitcollector.on('end')是事件绑定方法,它返回的是收集器实例而非Promise,所以await collector.on('end', ...)完全起不到等待收集器结束的作用。后面的if (await approvalChoice != "approved") return;会在用户还没点击按钮时就立刻执行——此时approvalChoice还没被赋值,自然是undefined。对普通变量使用
await无意义approvalChoice是普通字符串变量,不是异步Promise对象,await approvalChoice不会让代码等待它被赋值,只会直接返回它当前的初始值(undefined)。
修复方案:将收集器逻辑封装为Promise
要正确等待用户的按钮交互并获取选择值,我们可以把收集器逻辑包装成Promise,通过await来等待用户操作完成。以下是修改后的完整代码:
let senderID = interaction.member.user.id; const filter = i => (i.customId === `approved_${senderID}` || i.customId === `denied_${senderID}`) && i.user.id === senderID; // 将收集器逻辑封装为Promise const getApprovalChoice = () => { return new Promise((resolve) => { const collector = interaction.channel.createMessageComponentCollector({ filter, time: 60000 }); collector.on('collect', async i => { let choice; if (i.customId === `approved_${senderID}`) { await i.update({ content: 'Operation approved.', components: [] }); choice = "approved"; } else if (i.customId === `denied_${senderID}`) { await i.update({ content: 'Operation cancelled.', components: [] }); choice = "denied"; } collector.stop(); resolve(choice); // 将用户选择传递给Promise }); collector.on('end', (collected) => { // 处理超时未交互的情况,返回默认值 if (!collected.size) resolve(undefined); }); }); }; // 等待用户完成选择 const approvalChoice = await getApprovalChoice(); // 现在可以正常判断选择结果 if (approvalChoice !== "approved") { await interaction.deleteReply(); return; } // 若用户选择approved,执行后续处理逻辑 await interaction.editReply({content: "_**Processing...**_"});
关键改动说明
- 把收集器逻辑放进返回Promise的函数
getApprovalChoice中,当用户点击按钮或收集器超时结束时,通过resolve()传递选择结果。 - 使用
await getApprovalChoice()等待用户操作完成,确保approvalChoice能正确拿到用户的选择值(或超时后的undefined)。 - 移除了原代码中无效的异步等待逻辑,让代码执行顺序更符合预期——先等待用户选择,再判断结果执行后续操作。
这样修改后,你就能正确获取用户的按钮选择,代码也会按照预期流程执行啦。
内容的提问来源于stack exchange,提问作者Nihad Badalov
相关产品推荐
相关产品推荐

