gpt4 book ai didi

node.js - Discord.js awaitReaction 链式 promise 在 message.react 收集 react 后 promise 未解决

转载 作者:行者123 更新时间:2023-12-02 00:51:33 25 4
gpt4 key购买 nike

我正在研究 message.react 函数和 awaitReactions功能,我注意到一些困扰我的事情。

我试图确定是否应该为以下方法使用收集器或 client.on('messageReactionAdd')(这是另一个问题):

  1. 发送消息
  2. 对其添加 react
  3. 每次添加 react 时做某事(持续 X 秒)

所以我首先做了一个简单的示例,使用一个每次都返回 true 的过滤器,并且我注意到收集器正在收集我的机器人添加到消息中的最后一个表情符号。这是代码

const emojiNext = '➡';
const emojiPrevious = '⬅';
const emojiClap = '👏';

function filter(reaction) {
console.log('reacted to: ', reaction.emoji.name);
return true;
}
function sleep(ms, a){
return new Promise(resolve=>{
setTimeout(resolve,ms);
}).then(d => a);
}

function sendList(channel){
channel.send('foo')
.then(msg => {
console.log('First');
return msg.react(emojiPrevious);
})
.then(msgReaction => {
console.log('Second', msgReaction.message.reactions.keys());
return msgReaction.message.react(emojiNext);
})
.then(msgReaction => {
console.log('Third', msgReaction.message.reactions.keys());
return msgReaction.message.react(emojiClap);
})
// .then(msgReaction =>{
// return sleep(100, msgReaction);
// })
.then(msgReaction => {
console.log('Fourth', msgReaction.message.reactions.keys());
msgReaction.message.awaitReactions(filter, {max: 2, time: 1000, errors: ['time']})
.then(collected => {
console.log('ending', collected);
})
.catch(collected => {
console.log(`After 5 sec, only ${collected.size} out of 2 reacted: ${collected.map((v,k) => k)}`);
});
});
}

调试

这个例子比我做的第一个例子更成熟一些,因为我尝试了一些调试。

该示例发送一条消息,附加 chained promise 3 个表情符号,然后开始收集表情符号。然而,正如下面的日志所示,收集了最后一个表情符号(我自己从来没有按过任何表情符号,而且我一个人在我的服务器上):

First
Second [Map Iterator] { '⬅' }
Third [Map Iterator] { '⬅', '➡' }
Fourth [Map Iterator] { '⬅', '➡', '👏' }
reacted to: 👏
After 5 sec, only 1 out of 2 reacted: 👏

有时(视情况而定)它工作正常并且日志如下所示:

First
Second [Map Iterator] { '⬅' }
Third [Map Iterator] { '⬅', '➡' }
Fourth [Map Iterator] { '⬅', '➡', '👏' }
After 5 sec, only 0 out of 2 reacted:

我最后在火车上测试,网络不规则可能是原因。

所以我尝试了其他方法,我添加了 sleep 函数,它接受一个 ms 的量和一个值,并返回一个 promise,它会在 ms 的量过去后返回值。 (取消注释 3 行以进行此调试)。这样收藏家永远不会收集到最后一个表情符号。

我还尝试用收集器返回 then 之前的 promise (let res = await channel.send...) 然后执行其余代码.我仍然收集了最后一个表情符号。

我知道我可以使用我的过滤器来忽略机器人或我的表情符号,只关注用户的(见下面的代码)但我想知道是什么导致了这种行为。是不是我做的不好?我对 promise 有什么不理解的地方吗?

function filter(reaction, user) {
if(user.id === client.user.id) { return false; } // or user.bot to ignore all bot
console.log('reacted to: ', reaction.emoji.name);
return true;
}

在我看来,在调试中看到收集器在记录所有内容后使用react后,我认为正在解决的 promise 和 Discord 将信息发送到收集器/回调是不同的,但这只是一个猜测

注意:
node.js 版本:v11.15.0
discord.js 版本:v11.5.1

最佳答案

这是因为在与 Discord 交互时,REST APIGateway 是分开的。

在后端,message.react 导致 discord.js 向 Discord 的 REST API 发出请求 - Discord 将接收此请求、处理它并返回响应,从而导致返回的 promise通过 message.react 解决或拒绝。

但是,当您监听 react 时,它根本没有监听 REST API,它监听的是网关事件 - 这些主要是导致 client.on( 'messageReactionAdd') 在客户端发出。

当您收到来自 discord 的回复说您的 react 已成功发布时,discord 还没有完成发送您对所有客户端(包括您的机器人)的 react 的 messageReactionAdd 事件!它可能有,但也可能没有。然而,您在收到 API 响应后立即开始监听来自网关的响应。这就是所谓的竞争条件 - Discord 负责 REST API 的服务器正在与其负责网关的服务器竞争,看谁先将那条信息发送给您的机器人。

这不是您可以合理避免的事情,因为您绝对无法知道网关何时会 catch 事件并向您的机器人发送它自己的 react - 所以您在这里应该做的是考虑竞争条件您的过滤器,正如您在问题中所承认的那样。另一种解决方案可能涉及添加一个 react 事件监听器,并且仅在监听器检测到您的机器人的 react 已通过网关后才开始监听新的 react ,但这对于这种特定情况来说不太干净。


顺便说一句,我强烈建议使用 async/await 而不是那些丑陋且不可读的 promise 链。您的代码可以简化为:

async function sendList(channel){
let msg = await channel.send('foo');
console.log('First');
let msgReaction = await msg.react(emojiPrevious);
console.log('Second', msgReaction.message.reactions.keys());
msgReaction = await msg.react(emojiNext);
console.log('Third', msgReaction.message.reactions.keys());
msgReaction = await msg.react(emojiClap);
console.log('Fourth', msgReaction.message.reactions.keys());
try {
let collected = await msgReaction.message.awaitReactions(filter, {max: 2, time: 1000, errors: ['time']})
console.log('ending', collected);
} catch(partialCollection) {
console.log(`After 5 sec, only ${partialCollection.size} out of 2 reacted: ${partialCollection.map((v,k) => k)}`);
}
}

应该与您当前的代码完全相同,但在我看来更易读。

关于node.js - Discord.js awaitReaction 链式 promise 在 message.react 收集 react 后 promise 未解决,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57207625/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com