Discord.js Bot Sharding中broadcastEval返回对象方法丢失处理问询
discord.js Sharding模式下broadcastEval使用方案
核心结论
不需要手动构造Guild对象,最优方案是将所有涉及discord.js类实例方法调用的逻辑全部放在broadcastEval传入的函数内部执行,仅返回可序列化的纯数据即可。
你看到的返回值为数组是broadcastEval的默认行为:该方法会在所有激活的分片上执行传入函数,返回结果是每个分片的执行结果组成的数组,而你需要的目标Guild仅存在于负责管理对应服务器ID的单个分片上,其他分片执行查询逻辑会返回无效结果。
优化实现(匹配你获取服务器用户昵称的需求)
async function serverLookup(client, { sID, authNm }) { // 提前判断当前分片是否持有目标服务器,过滤无效执行 if (!client.guilds.cache.has(sID)) return null; try { const svrInfo = await client.guilds.fetch(sID); // 直接在分片内部完成成员拉取、昵称读取逻辑 const allMembers = await svrInfo.members.fetch(); // 整理为纯对象数组返回,仅保留需要的基础数据字段 return allMembers.map(member => ({ userId: member.id, userName: member.user.username, displayName: member.nickname ?? member.user.username })); } catch (err) { console.error('查询失败:', err); return null; } } // 先计算目标服务器所属的分片ID,仅指定该分片执行逻辑 const targetShard = bot.shard.idsForGuild(serverID); const execResult = await bot.shard.broadcastEval(serverLookup, { context: { sID: serverID, authNm: msgAuthor }, shard: targetShard }); // 过滤无效值后拿到最终需要的用户昵称列表 const memberNicknameList = execResult.filter(Boolean)[0];
注意事项
- 禁止在
broadcastEval外部调用discord.js类实例的内置方法,跨分片传递的所有数据都会经过JSON序列化,会丢失类实例的所有挂载方法,手动重构实例成本极高且容易出现缓存不一致问题,完全没有必要性。 - 调用
broadcastEval时指定目标分片,既可以减少不必要的性能开销,也能避免返回结果中出现大量无效的空值,简化后续数据处理逻辑。
内容的提问来源于stack exchange,提问作者BotBitBanger
相关产品推荐
相关产品推荐

