Discord 机器人在添加大量角色时遇到问题...抱怨事件监听器
Discord bot having trouble adding lots of roles... complains about event listeners
我有一个 Discord 机器人可以更新我们 Discord 上的排行榜频道。每次在数据库中记录一场比赛时,机器人都会获取排行榜数据,然后对于它遇到的每个 memberId,它会删除所有技能徽章(更高的技能等于更高声望的徽章),然后根据他们当前的技能添加正确的徽章.出于某种原因,连续添加大量成员角色导致机器人只能通过前 100 名中的大约 15 个成员。我对 js 很陌生,但我认为每个 addRole 命令都会触发 GuildMemberUpdate 事件,而且处理起来实在是太多了。这是我收到的警告信息。接下来是大量添加角色超时错误(我将包括一个)。
(node:612) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 guildMemberUpdate listeners added. Use emitter.setMaxListeners() to increase limit
at _addListener (events.js:280:19)
at Client.addListener (events.js:297:10)
at Promise (/home/ubuntu/bots/node_modules/discord.js/src/client/rest/RESTMethods.js:511:19)
at new Promise (<anonymous>)
at RESTMethods.addMemberRole (/home/ubuntu/bots/node_modules/discord.js/src/client/rest/RESTMethods.js:501:12)
at GuildMember.addRole (/home/ubuntu/bots/node_modules/discord.js/src/structures/GuildMember.js:453:37)
at C6Leaderboard.applyTags (/home/ubuntu/bots/modules/leaderboard.js:139:17)
at C6Leaderboard.createLeaderboard (/home/ubuntu/bots/modules/leaderboard.js:110:18)
at C6Leaderboard.publishLeaderboard (/home/ubuntu/bots/modules/leaderboard.js:67:29)
at <anonymous>
Error: Adding the role timed out.
at timeout.client.setTimeout (/home/ubuntu/bots/node_modules/discord.js/src/client/rest/RESTMethods.js:514:16)
at Timeout.setTimeout [as _onTimeout] (/home/ubuntu/bots/node_modules/discord.js/src/client/Client.js:433:7)
at ontimeout (timers.js:475:11)
at tryOnTimeout (timers.js:310:5)
at Timer.listOnTimeout (timers.js:270:5)
这是我的模块代码的要点:
class C6Leaderboard
{
constructor() {
util.client.on('ready', () =>
{
guild = util.client.guilds.get("291751672106188800");
this.generate(); //generate an up to date leaderboard
});
}
async generate()
{
try
{
// Grab data
this.leaderboard = await util.makeRGRequest('leaderboard.php', {});
// Publish new Leaderboard
this.publishLeaderboard();
}
catch(err)
{
console.log('[leaderboard_err]' + err);
}
}
async publishLeaderboard()
{
const channel = util.getChannel(483346000233365526);
const msg = await channel.fetchMessage(channel.lastMessageID());
const content_new = this.createLeaderboard();
if( msg.content != content_new) msg.edit( content_new );
}
createLeaderboard(i, max_top)
{
//loop through leaderboard data
//print line of leaderboard message
this.applyTags(this.leaderboard[i].id, this.leaderboard[i].skill);
}
async applytags(id, skill)
{
if (!guild)
return;
let mem = guild.members.get(id);
if (!mem)
return;
mem.removeRoles(difficulties);
if (skill < 1500)
mem.addRole(settler).catch(console.error);
else if (skill >= 1500 && skill < 1600)
mem.addRole(chieftain).catch(console.error);
else if (skill >= 1600 && skill < 1700)
mem.addRole(warlord).catch(console.error);
else if (skill >= 1700 && skill < 1800)
mem.addRole(prince).catch(console.error);
else if (skill >= 1800 && skill < 1900)
mem.addRole(king).catch(console.error);
else if (skill >= 1900 && skill < 2000)
mem.addRole(emperor).catch(console.error);
else if (skill >= 2000 && skill < 2100)
mem.addRole(immortal).catch(console.error);
else if (skill >= 2100)
mem.addRole(deity).catch(console.error);
}
}
return Promise 需要使用 await 调用且不能嵌套的方法。
async function applytags(id, skill)
{
if (!guild)
return;
let mem = await guild.members.get(id);
if (!mem)
return;
await mem.removeRoles(difficulties);
if (skill < 1500)
await mem.addRole(settler).catch(console.error);
else if (skill >= 1500 && skill < 1600)
await mem.addRole(chieftain).catch(console.error);
else if (skill >= 1600 && skill < 1700)
await mem.addRole(warlord).catch(console.error);
else if (skill >= 1700 && skill < 1800)
await mem.addRole(prince).catch(console.error);
else if (skill >= 1800 && skill < 1900)
await mem.addRole(king).catch(console.error);
else if (skill >= 1900 && skill < 2000)
await mem.addRole(emperor).catch(console.error);
else if (skill >= 2000 && skill < 2100)
await mem.addRole(immortal).catch(console.error);
else if (skill >= 2100)
await mem.addRole(deity).catch(console.error);
}
- https://anidiots.guide/other-guides/async-await
- https://hackernoon.com/javascript-promises-and-why-async-await-wins-the-battle-4fc9d15d509f
- https://medium.com/@tkssharma/writing-neat-asynchronous-node-js-code-with-promises-async-await-fa8d8b0bcd7c
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
我有一个 Discord 机器人可以更新我们 Discord 上的排行榜频道。每次在数据库中记录一场比赛时,机器人都会获取排行榜数据,然后对于它遇到的每个 memberId,它会删除所有技能徽章(更高的技能等于更高声望的徽章),然后根据他们当前的技能添加正确的徽章.出于某种原因,连续添加大量成员角色导致机器人只能通过前 100 名中的大约 15 个成员。我对 js 很陌生,但我认为每个 addRole 命令都会触发 GuildMemberUpdate 事件,而且处理起来实在是太多了。这是我收到的警告信息。接下来是大量添加角色超时错误(我将包括一个)。
(node:612) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 guildMemberUpdate listeners added. Use emitter.setMaxListeners() to increase limit
at _addListener (events.js:280:19)
at Client.addListener (events.js:297:10)
at Promise (/home/ubuntu/bots/node_modules/discord.js/src/client/rest/RESTMethods.js:511:19)
at new Promise (<anonymous>)
at RESTMethods.addMemberRole (/home/ubuntu/bots/node_modules/discord.js/src/client/rest/RESTMethods.js:501:12)
at GuildMember.addRole (/home/ubuntu/bots/node_modules/discord.js/src/structures/GuildMember.js:453:37)
at C6Leaderboard.applyTags (/home/ubuntu/bots/modules/leaderboard.js:139:17)
at C6Leaderboard.createLeaderboard (/home/ubuntu/bots/modules/leaderboard.js:110:18)
at C6Leaderboard.publishLeaderboard (/home/ubuntu/bots/modules/leaderboard.js:67:29)
at <anonymous>
Error: Adding the role timed out.
at timeout.client.setTimeout (/home/ubuntu/bots/node_modules/discord.js/src/client/rest/RESTMethods.js:514:16)
at Timeout.setTimeout [as _onTimeout] (/home/ubuntu/bots/node_modules/discord.js/src/client/Client.js:433:7)
at ontimeout (timers.js:475:11)
at tryOnTimeout (timers.js:310:5)
at Timer.listOnTimeout (timers.js:270:5)
这是我的模块代码的要点:
class C6Leaderboard
{
constructor() {
util.client.on('ready', () =>
{
guild = util.client.guilds.get("291751672106188800");
this.generate(); //generate an up to date leaderboard
});
}
async generate()
{
try
{
// Grab data
this.leaderboard = await util.makeRGRequest('leaderboard.php', {});
// Publish new Leaderboard
this.publishLeaderboard();
}
catch(err)
{
console.log('[leaderboard_err]' + err);
}
}
async publishLeaderboard()
{
const channel = util.getChannel(483346000233365526);
const msg = await channel.fetchMessage(channel.lastMessageID());
const content_new = this.createLeaderboard();
if( msg.content != content_new) msg.edit( content_new );
}
createLeaderboard(i, max_top)
{
//loop through leaderboard data
//print line of leaderboard message
this.applyTags(this.leaderboard[i].id, this.leaderboard[i].skill);
}
async applytags(id, skill)
{
if (!guild)
return;
let mem = guild.members.get(id);
if (!mem)
return;
mem.removeRoles(difficulties);
if (skill < 1500)
mem.addRole(settler).catch(console.error);
else if (skill >= 1500 && skill < 1600)
mem.addRole(chieftain).catch(console.error);
else if (skill >= 1600 && skill < 1700)
mem.addRole(warlord).catch(console.error);
else if (skill >= 1700 && skill < 1800)
mem.addRole(prince).catch(console.error);
else if (skill >= 1800 && skill < 1900)
mem.addRole(king).catch(console.error);
else if (skill >= 1900 && skill < 2000)
mem.addRole(emperor).catch(console.error);
else if (skill >= 2000 && skill < 2100)
mem.addRole(immortal).catch(console.error);
else if (skill >= 2100)
mem.addRole(deity).catch(console.error);
}
}
return Promise 需要使用 await 调用且不能嵌套的方法。
async function applytags(id, skill)
{
if (!guild)
return;
let mem = await guild.members.get(id);
if (!mem)
return;
await mem.removeRoles(difficulties);
if (skill < 1500)
await mem.addRole(settler).catch(console.error);
else if (skill >= 1500 && skill < 1600)
await mem.addRole(chieftain).catch(console.error);
else if (skill >= 1600 && skill < 1700)
await mem.addRole(warlord).catch(console.error);
else if (skill >= 1700 && skill < 1800)
await mem.addRole(prince).catch(console.error);
else if (skill >= 1800 && skill < 1900)
await mem.addRole(king).catch(console.error);
else if (skill >= 1900 && skill < 2000)
await mem.addRole(emperor).catch(console.error);
else if (skill >= 2000 && skill < 2100)
await mem.addRole(immortal).catch(console.error);
else if (skill >= 2100)
await mem.addRole(deity).catch(console.error);
}
- https://anidiots.guide/other-guides/async-await
- https://hackernoon.com/javascript-promises-and-why-async-await-wins-the-battle-4fc9d15d509f
- https://medium.com/@tkssharma/writing-neat-asynchronous-node-js-code-with-promises-async-await-fa8d8b0bcd7c
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function