使用discord.js开发公告机器人遇awaitMessages未定义错误求助
解决discord.js中
awaitMessages报"Cannot read property 'awaitMessages' of undefined"的问题 嘿,我来帮你搞定这个报错!你遇到的TypeError其实是个discord.js里的常见小坑——你直接访问的msg.member.dmChannel可能还没被创建出来。当你第一次给用户发DM的时候,Discord不会立刻生成DM通道对象,这时候dmChannel就是undefined,自然调用不了awaitMessages啦。
另外看你的代码还有几个小问题:多层嵌套的.then()简直是回调地狱,读起来头疼;catch块里直接创建Embed是无效的;还有变量没加let/const,容易搞出全局污染;最后Embed创建的顺序也有点问题,可能导致未定义就使用的情况。
修复后的代码(用async/await简化流程)
我把你的代码重构了一下,用async/await替代嵌套回调,同时确保DM通道存在,还统一了错误处理:
const allyAnnouncementChannel = client.channels.cache.get('756701256122236941'); // 假设Ping、Title、Message、Image、ImageURL、Finished都是你定义的提示文本 if (msg.content === '-na') { // 先检查是不是在DM里用指令 if (msg.channel.type === 'DM') { return msg.reply('请在服务器频道里用这个指令哦!'); } // 检查用户有没有权限角色 if (!msg.member.roles.cache.has('756713479003701338')) { return msg.reply('你没有使用这个指令的权限哒!'); } try { // 先创建/获取用户的DM通道,确保它存在 const dmChannel = await msg.author.createDM(); // 第一步:收集Ping内容 await dmChannel.send(Ping); const pingCollected = await dmChannel.awaitMessages({ filter: m => m.author.id === msg.author.id, max: 1, time: 300000, // 5分钟超时 errors: ['time'] }); const embedPing = pingCollected.first().content; // 第二步:收集公告标题 await dmChannel.send(Title); const titleCollected = await dmChannel.awaitMessages({ filter: m => m.author.id === msg.author.id, max: 1, time: 300000, errors: ['time'] }); const embedTitle = titleCollected.first().content; // 第三步:收集公告内容 await dmChannel.send(Message); const messageCollected = await dmChannel.awaitMessages({ filter: m => m.author.id === msg.author.id, max: 1, time: 300000, errors: ['time'] }); const embedMessage = messageCollected.first().content; // 第四步:询问是否需要添加图片 await dmChannel.send(Image); const imageConfirmCollected = await dmChannel.awaitMessages({ filter: m => m.author.id === msg.author.id, max: 1, time: 300000, errors: ['time'] }); const needImage = imageConfirmCollected.first().content.toLowerCase() === 'yes'; // 先创建基础Embed let announcementEmbed = new Discord.MessageEmbed() .setColor('#FFD700') .setTitle(embedTitle) .setDescription(embedMessage) .setTimestamp() .setFooter(`Sent By: ${msg.author.tag}`); if (needImage) { await dmChannel.send(ImageURL); const imageUrlCollected = await dmChannel.awaitMessages({ filter: m => m.author.id === msg.author.id, max: 1, time: 300000, errors: ['time'] }); const embedImage = imageUrlCollected.first().content; announcementEmbed.setImage(embedImage); await dmChannel.send('图片已添加,马上发送公告!'); } else { await dmChannel.send(Finished); } // 把公告发到指定频道 await allyAnnouncementChannel.send(embedPing, announcementEmbed); await dmChannel.send('公告发送成功啦!'); } catch (error) { // 处理超时或其他错误 const cancelEmbed = new Discord.MessageEmbed() .setColor('#FFD700') .setTitle('Announcement Cancelled') .setDescription('It has been 5 minutes without a response. The announcement has been cancelled.') .setFooter('Please do the command again if you wish to send an announcement.'); await msg.author.send({ embeds: [cancelEmbed] }); } }
关键改进说明
- 确保DM通道存在:用
msg.author.createDM()方法,它会返回一个Promise,保证DM通道已经创建好,再也不会出现dmChannel为undefined的情况。 - 告别回调地狱:用
async/await把异步代码写成同步风格,读起来和维护起来都轻松多了。 - 统一错误处理:一个
try/catch搞定所有超时和异常,不用重复写四次相同的错误Embed了。 - 变量规范:用
const/let声明变量,避免全局污染,命名也改成了JavaScript常用的小驼峰格式。 - 逻辑优化:调整了Embed创建的顺序,确保所有变量都初始化后再使用,避免出现未定义的错误。
内容的提问来源于stack exchange,提问作者MrLlamaDev




