Discord.js 编写!message指令向提及用户发私信时出现undefined属性读取报错
Discord.js 自定义私信指令报错修正
报错核心原因
逐行对应现有代码的逻辑问题,完全匹配控制台报错的触发链路:
- 变量覆盖冲突:在分支内用
var message = args[2]直接覆盖了外层传入的Discord消息对象,后续代码里调用message.author时,实际拿到的是args[2]截取的字符串片段,字符串本身不存在author属性,读取嵌套属性author.username时就会抛出Cannot read property 'username' of undefined的类型错误 - 取值逻辑错位:把
args[1]赋值给username后直接尝试读取username.id,但args[1]是指令文本拆分出的字符串,本身没有id属性;同时guild.members.fetch()是异步接口,没有做Promise处理,直接链式调用message.send的结构本身就不符合Discord.js的API设计 - 异步操作无捕获:所有涉及网络请求的API方法都没有加异常捕获,Promise执行失败时就会触发未处理的Promise拒绝警告
修正后可运行代码
注意代码所在的消息事件回调必须声明为async才能正常使用异步等待逻辑:
client.on('messageCreate', async (message) => { // 跳过机器人发送的消息,避免逻辑死循环 if (message.author.bot) return; const args = message.content.trim().split(/ +/g); const cmd = args.shift().toLowerCase(); if (cmd === '!message') { // 未检测到提及用户时提示用法 if (!message.mentions.users.size) { return message.channel.send("```用法示例: !message @目标用户 要发送的内容```"); } // 直接从提及列表取第一个被@的服务器成员 const targetMember = message.mentions.members.first(); // 拼接除了指令、@提及之外的所有文本作为私信正文 const privateMsg = args.slice(1).join(' '); // 未输入私信正文时给出提示 if (!privateMsg) { return message.channel.send("```请输入需要发送的私信内容```"); } // 发送私信并捕获异常 try { await targetMember.user.send(`${message.author.tag} 给你发送了一条站内私信: ${privateMsg}`); message.channel.send(`消息已成功发送给 ${targetMember.user.tag}`); } catch (sendErr) { message.channel.send("```发送失败:目标用户关闭了服务器私信接收权限```"); } } })
额外注意事项
- 禁止用
var声明会覆盖外层作用域的变量,优先使用const/let做块级作用域声明,避免意外的变量提升、覆盖问题 - Discord.js v14+版本已经废弃了原来的
message事件,统一替换为messageCreate事件,继续使用老事件会出现API找不到的兼容问题 - 所有涉及接口请求的方法(成员拉取、消息发送)都需要做异常捕获,避免因为用户关闭私信、网络波动等情况触发未处理的Promise警告
内容的提问来源于stack exchange,提问作者dayofpay
相关产品推荐
相关产品推荐

