Discord.js报错:Cannot read property 'send' of undefined 求助
解决Discord.js中
TypeError: Cannot read property 'send' of undefined问题 首先,咱们先拆解这个错误:TypeError: Cannot read property 'send' of undefined 说明你调用.send()的msg.author对象变成了undefined。结合你的代码来看,主要问题出在多层嵌套的Promise回调地狱导致的上下文不稳定,还有变量定义顺序的逻辑错误。下面是具体的分析和修复方案:
核心问题分析
- 回调地狱导致的上下文丢失:你嵌套了4层
.awaitMessages()的.then()回调,虽然理论上闭包应该保留msg的引用,但这种深层嵌套很容易因为异步流程的不确定性导致msg或msg.author的引用失效。 - 变量定义顺序错误:在
yes分支里,你先调用了allyAnnouncementChannel.send(EmbedPing, FinishedEmbed),但FinishedEmbed是在else分支之后才定义的,这不仅会引发另一个错误,还可能打乱整个流程的执行顺序,间接导致msg.author的异常。 - 缺少错误防护:没有对
msg.author的存在性做校验,也没有处理用户关闭DM权限这类边界情况。
修复后的代码(用async/await重构)
我把你的代码改成了async/await风格,彻底避免回调地狱,同时修复了逻辑错误:
client.on('message', async msg => { if (msg.content === '-na') { // 跳过DM频道的请求 if (msg.channel instanceof Discord.DMChannel) { return; } // 校验用户角色 if (!msg.member.roles.cache.has('756713479003701338')) { return; } try { // 收集Ping内容 await msg.author.send(Ping); const pingCollect = await msg.author.dmChannel.awaitMessages( m => m.author.id === msg.author.id, { max: 1, time: 300000 } ); const EmbedPing = pingCollect.first().content; // 收集Title内容 await msg.author.send(Title); const titleCollect = await msg.author.dmChannel.awaitMessages( m => m.author.id === msg.author.id, { max: 1, time: 300000 } ); const EmbedTitle = titleCollect.first().content; // 收集Message内容 await msg.author.send(Message); const messageCollect = await msg.author.dmChannel.awaitMessages( m => m.author.id === msg.author.id, { max: 1, time: 300000 } ); const EmbedMessage = messageCollect.first().content; // 确认是否需要图片 await msg.author.send(Image); const confirmCollect = await msg.author.dmChannel.awaitMessages( m => m.author.id === msg.author.id, { max: 1, time: 300000 } ); const needImage = confirmCollect.first().content.toLowerCase(); if (needImage === 'yes') { // 收集图片URL await msg.author.send(ImageURL); const imageUrlCollect = await msg.author.dmChannel.awaitMessages( m => m.author.id === msg.author.id, { max: 1, time: 300000 } ); const EmbedImage = imageUrlCollect.first().content; // 创建带图片的嵌入并发送 const finishedEmbedWithImage = new Discord.MessageEmbed() .setColor('#FFD700') .setTitle(EmbedTitle) .setDescription(EmbedMessage) .setImage(EmbedImage) .setTimestamp() .setFooter(`Sent By: ${msg.author.tag}`); await allyAnnouncementChannel.send(EmbedPing, finishedEmbedWithImage); } else { // 发送完成提示(先校验msg.author存在) if (msg.author) { await msg.author.send(Finished).catch(err => console.error('发送DM失败:', err)); } // 创建不带图片的嵌入并发送 const finishedEmbed = new Discord.MessageEmbed() .setColor('#FFD700') .setTitle(EmbedTitle) .setDescription(EmbedMessage) .setTimestamp() .setFooter(`Sent By: ${msg.author.tag}`); await allyAnnouncementChannel.send(EmbedPing, finishedEmbed); } } catch (err) { // 处理超时或用户取消的情况 if (msg.author) { msg.author.send('操作已取消或超时,请重新发起请求。').catch(err => console.error('发送取消提示失败:', err)); } console.error('流程执行出错:', err); } } });
关键修复点说明
- 用async/await替代回调嵌套:代码结构更清晰,彻底避免了闭包上下文丢失的问题,
msg的引用会全程稳定。 - 添加
msg.author存在性校验:在所有发送DM的操作前先确认msg.author不为undefined,从根源上解决报错。 - 修复变量定义顺序错误:把
FinishedEmbed的定义移到对应分支内部,避免引用未初始化的变量。 - 规范用户信息展示:用
msg.author.tag替代直接拼接用户对象,避免格式异常(tag是用户名+# discriminator的标准格式)。 - 完整的错误捕获:统一用
try/catch处理超时、用户取消、DM权限关闭等异常情况,避免程序崩溃。
额外建议
- 提前校验
allyAnnouncementChannel的有效性,避免发送公告时出错:if (!allyAnnouncementChannel) { console.error('无法找到指定的公告频道!'); return; } - 确保所有Embed常量(Ping、Title、Message等)都已正确初始化,没有拼写错误。
内容的提问来源于stack exchange,提问作者MrLlamaDev
相关产品推荐
相关产品推荐

