discord.js开发中member无明确原因返回undefined走入else分支
问题描述
运行下述代码时,程序始终走入else分支,无法进入预期的if (member)判断逻辑返回对应结果。
前置说明:已排除「目标用户不在当前服务器(Guild)」这一常见诱因,该场景下用户确实存在于目标服务器内,运行截图参考:
问题代码如下:
let member = msg.mentions.members.first() || msg.guild.members.cache.get(args[0]); console.log(member); if (member) { try { const userInfo = new MessageEmbed() .setAuthor({ name: `${member.user.tag}`, iconURL: member.user.displayAvatarURL({ dynamic: true }) }) .setColor("BLUE") .setThumbnail(member.user.displayAvatarURL({ dynamic: true })) .setTitle("User Info") .setDescription( `**Tag:** ${member.user.tag}\n**ID:** ${member.user.id}\n**Bot:** ${member.user.bot ? "✅" : "❌"}\n**Created At: <t:${Math.round(parseInt(member.user.createdTimestamp) / 1000)}:F>**\n**Joined At: <t:${Math.round( parseInt(member.joinedTimestamp) / 1000 )}:F>**` ) .setTimestamp(); return msg.channel.send({ embeds: [userInfo] }); } catch (err) { log(err); return; } } else { try { let fetching = await client.users.fetch(args[0]); const userInfo = new MessageEmbed() .setAuthor({ name: `${fetching.tag}`, iconURL: fetching.displayAvatarURL({ dynamic: true }) }) .setColor("BLUE") .setThumbnail(fetching.displayAvatarURL({ dynamic: true })) .setTitle("User Info") .setDescription(`**Tag:** ${fetching.tag}\n**ID:** ${fetching.id}\n**Bot:** ${fetching.bot ? "✅" : "❌"}\n**Joined At: <t:${Math.round(parseInt(fetching.createdTimestamp) / 1000)}:F>**`) .setTimestamp(); return msg.channel.send({ embeds: [userInfo] }); } catch (err) { log(err); return; } }
故障原因
- Discord.js 默认不会全量缓存服务器内的所有成员,
msg.guild.members.cache仅存储客户端当前已缓存的成员对象。即使用户真实存在于服务器中,只要未触发缓存逻辑,cache.get(args[0])就会返回undefined。 - 如果未在Discord开发者后台为Bot开启服务器成员特权意图,
msg.mentions.members也无法正确抓取被@的成员对象,最终赋值给member的结果为假值,直接走入else分支。 - 如果传入的
args[0]是带格式的提及字符串(如<@!1234567890>),直接作为ID传入缓存查询也会匹配失败。
修复方案
- 登录Discord开发者后台,进入对应Bot的设置页,在「Privileged Gateway Intents」分类下开启Server Members Intent开关,保存后重启Bot。
- 替换原有的仅读缓存的成员获取逻辑,优先读取缓存,缓存不存在时主动调用
fetch拉取成员,同时增加ID清洗逻辑处理带格式的提及串:
// 清洗用户ID,处理<@!123>这类带格式的入参 const targetId = args[0]?.replace(/[<@!>]/g, ''); let member = msg.mentions.members.first(); if (!member && targetId) { try { // 主动拉取成员,不受本地缓存限制 member = await msg.guild.members.fetch(targetId); } catch (e) { member = null; } } // 后续原有if/else判断逻辑保持不变即可
内容的提问来源于stack exchange,提问作者Itz-Toothless
相关产品推荐
相关产品推荐


