我正在尝试使用节点在Discord上创建一个机器人。js模块不一致。js,在它的一个命令中,它遍历公会(服务器)中的成员地图,并将所有成员都禁用。以下是我使用的代码:
const Discord = require('discord.js');
const client = new Discord.Client();
const map = new Map();
client.once('ready', () => {
// This is just for demonstration purposes. In the actual code, the values are all different
// members and the keys are their respective IDs. This is inside the "ready" event because
// otherwise the client's cache would be empty.
const hjtunfgb = client.guilds.cache.get('myServerID').members.cache.get('myID');
map.set(0, hjtunfgb);
map.set(1, hjtunfgb);
map.set(2, hjtunfgb);
map.set(3, hjtunfgb);
map.set(4, hjtunfgb);
map.set(5, hjtunfgb);
map.set(6, hjtunfgb);
map.set(7, hjtunfgb);
map.set(8, hjtunfgb);
map.set(9, hjtunfgb);
console.log(`Logged in as ${client.user.tag}!`);
});
client.on('message', message => {
// Here I have two commands: "foo", which mutes everyone in the Map, and "bar", which does other
// stuff that is not relevant to the problem
if (message.content.toLowerCase() === 'foo') {
map.forEach((member, n) => {
// member.voice.setMute(true) is how the bot mutes people. It returns a promise, that
// rejects if the member is not connected to any voice channel in that server.
member.voice.setMute(true)
.then(() => console.log(n + ' muted!'))
.catch(() => console.error(n + ' error!'));
});
} else if (message.content.toLowerCase() === 'bar') {
console.log('baz');
}
});
client.login('myBotsSecretLoginKey');
但是,如果一个成员没有连接到任何语音通道,setMute()方法创建的promise将被拒绝,并且在这里通过记录错误消息来处理它(同样,在实际代码中,拒绝被正确处理)。问题是,在拒绝之后,forEach会停止并不会执行,直到我再次执行“foo”,然后它才会执行。例如,如果我在聊天中发送“foo”,并在“4静音”后立即断开连接如果已记录,则输出如下所示:
0 muted!
1 muted!
2 muted!
3 muted!
4 muted!
5 error!
如果我连接或断开与语音频道的连接,则不会发生任何事情,如果我写入“bar”,则程序正常输出“baz”。然后,如果我加入一个语音频道并再次发送“foo”,则输出以下内容:
0 muted!
6 muted!
7 muted!
8 muted!
9 muted!
1 muted!
2 muted!
3 muted!
4 muted!
5 muted!
6 muted!
7 muted!
8 muted!
9 muted!
因此,在Map上调用了第一个foreach命令,这触发了之前的foreach恢复操作。相反,如果我调用foo,然后加入并第三次调用foo,则前一次调用0错误!
输出,后者的输出是
0 muted!
6 muted!
...
9 muted!
1 muted!
...
9 muted!
1 muted!
...
9 muted!
因此,即使拒绝得到处理,forEach也会停止拒绝promise。但是我需要forEach立即恢复,因为bot将不断地静音和取消静音,并且一个断开连接的成员不能阻止其他成员静音。我怎样才能解决这个问题?
编辑:使回调异步并在尝试中包装setMute。。。抓块并没有解决问题。而且,正如有人指出的,forEach确实在任何promise被拒绝之前运行到完成阶段——我通过控制台检查了这一点。运行前记录日志。setMute()。所以,问题在于node discord如何处理promise。js,或不和谐本身。有人能提供信息说明为什么会发生这种情况,以及如何避免这种情况?
我还试着用。。。使用数组而不是映射,但它们都产生了相同的问题。
编辑2:我可以通过更改“message”事件侦听器中的回调来解决此问题,如下所示:
client.on('message', async message => {
if (message.content.toLowerCase() === 'foo') {
for (const [n, member] of map) {
try {
await member.voice.setMute(true);
console.log(n + ' muted!');
} catch (error) {
console.error(n + ' error!');
}
}
} else if (message.content.toLowerCase() === 'bar') {
console.log('baz');
}
});
这样,代码在创建下一个promise之前会等待该promise得到解决。这并不是最理想的方式,因为这些promise可以并行运行,但不一致性会一次处理一个promise,因此在实践中不会影响性能。我尝试使用以下设置在不使用forEach的情况下并行运行promise:
client.on('message', message => {
if (message.content.toLowerCase() === 'foo') {
Promise.all(Array.from(map.entries()).map(async ([n, member]) => {
try {
await member.voice.setMute(true);
console.log(n + ' muted!');
} catch (error) {
console.error(n + ' error!');
}
}));
} else if (message.content.toLowerCase() === 'bar') {
console.log('baz');
}
});
但它也有同样的问题。问题似乎在于节点如何,不协调。js和/或Discord同时处理多个请求的promise。我能做些什么来解决这个问题?同步运行异步代码目前还可以,但从长远来看,并行运行它们会更好。我是否应该将此报告为discord的bug。js和/或Discord,或者有一个我不知道的目的(和修复)?
在没有看到整个过程的情况下,我无法肯定地告诉您出了什么问题,但人们强烈怀疑setMute
有时不会拒绝,而是抛出异常。在这种情况下,forEach将被终止。同样:您可以使用catch
处理promise拒绝,但如果发生异常,则不处理在setMute
中引发异常(通常,返回promise的函数不应编码为引发异常)。
现在,如果您将forEach内部的函数更改为async
,那么您可以在代码内部使用wait
,更重要的是,使用try/catch
捕获promise拒绝和抛出setMute
,如下所示:
client.on("message", (message) => {
if (message.content.toLowerCase() === "foo") {
map.forEach(async (member, n) => {
try {
await member.voice.setMute(true);
console.log(n + " muted!");
} catch (err) {
console.error(n + " error! " + err);
}
});
} else if (message.content.toLowerCase() === "bar") {
console.log("baz");
}
});
在forEach循环中不能使用promise(wait)。
看看这个问题。
在forEach循环中使用async/await
干杯
我得到这个错误- (节点:18420)未处理的PromisejectionWarning:TypeError:无法读取未定义的属性“name” (节点:18420)未处理的PromisejectionWarning:未处理的promise拒绝。此错误源于在没有catch块的情况下抛出异步函数的内部,或者拒绝使用未处理的promise。catch()。要在未处理的promise拒绝时终止节点进程,请
本文介绍了单个promise组合器: 但我没有看到的是,一种运行所有promise的方法,但不是在个人promise被拒绝时短路。我如何确保所有的promise都得到履行,但我能处理拒绝和所有promise的解决?
我想在Repl上为我的游戏实现一个基本的排行榜。它,所以我创建了一个节点。js后端。这是我在后端的配置: 但是每当我尝试发布时,我都会得到以下错误: (节点:344)未处理的PromisejectionWarning:TypeError:无法读取null的属性“push” (节点:344)UnhandledPromiseRejtionWarning:未处理的promise拒绝。这个错误要么是由于抛
我有以下验证函数检查用户是否存在: 以下使用Chai的测试应对此进行测试: 错误确实会被抛出,但是mocha在控制台中显示以下内容: 2)显示抛出,如果用户是未定义的(节点: 18587)UnhandledPromiseRejse警告:未处理的promise拒绝(拒绝id: 2):错误:用户不存在 所以我的问题是,我如何重写测试,让它捕捉到promise拒绝?
我正在努力在以下任务中发送多个AJAX调用。API返回有两个参数:和,并返回指定用户的最后10条消息,从指定的偏移量开始。如果偏移量大于用户的消息总数,API将返回空字符串。 我编写了一个函数,返回一个单独的promise,为指定的和获取10条消息。 我需要使用为多个运行并行任务,但是我无法为每个运行并行子任务(每次将
我正在与节点JS中的promise模式作斗争 我在db中寻找用户,然后用用户引用保存新实体,但当用户不在db中时,我应该返回拒绝,但我不确定如何正确地做到这一点。 有什么办法可以做得更好吗? btw:对不起,coffeescript :-[