Discord.js awaitReaction在message.react之后链接了诺言,因为未解决诺言而收集反应

问题描述 投票:3回答:1

[我当时正在使用message.react函数和awaitReactions函数,但发现有些困扰我。

我试图确定是否应该对以下方法使用收集器或awaitReactions(这是另一个问题):

  1. 发送消息
  2. 添加反应
  3. 每添加一个反应(X秒钟,每次都做某事)

因此,我做了一个简单的示例,开始时有一个每次返回client.on('messageReactionAdd')的过滤器,我注意到收集器正在收集我的机器人添加到消息中的最后一个表情符号。这是代码

true

Debug

此示例比我做的第一个示例要发达,因为我尝试了一些调试。

该示例发送一条消息,在其上附加链式允诺3个表情符号,然后开始收集表情符号。但是,如下面的日志所示,它收集了最后一个表情符号(我自己从未按过任何表情符号,而且我独自一人在服务器上):

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)}`);
    });
  });
}

但是有时(取决于它)它工作正常,并且日志如下所示:

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

我最近在火车上进行测试,但网络不正常,可能是原因。

因此,我尝试了其他方法,我添加了sleep函数,该函数接受一定数量的ms和一个值,然后返回一个promise,该数量将在经过ms数量后解析后返回该值。 (取消注释第3行以进行此调试)。这样,收集器就不会收集到最后一个表情符号。

[我还试图用收集器(First Second [Map Iterator] { '⬅' } Third [Map Iterator] { '⬅', '➡' } Fourth [Map Iterator] { '⬅', '➡', '👏' } After 5 sec, only 0 out of 2 reacted: )在then之前返回诺言,然后执行其余代码。我仍然收集了最后一个表情符号。

我知道我可以使用过滤器忽略bot或表情符号,而只关注用户的表情符号,但是我想知道是什么原因导致了这种行为。我有做不好的事吗?我对诺言有不了解的地方吗?

我认为,并且在调试中看到收集器在记录所有日志后做出反应之后,我认为已解决的诺言与Discord将信息发送到收集器/回调不同,但这只是一个猜测

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

node.js promise discord discord.js
1个回答
0
投票

这是由于与Discord交互时REST APIGateway之间的差异。

在后端,let res = await channel.send...导致discord.js触发对Discord的REST API的请求-Discord将接收此请求,对其进行处理并返回响应,这将导致message.react返回的诺言得以解决或拒绝。

但是,当您正在监听响应时,它根本就不在监听REST API,而是在监听网关事件-这些很大程度上是导致在客户端发出message.react之类的事件的原因。] >

[当您收到来自discord的答复说您的反应已成功发布时,discord尚未完成向服务器中的所有客户端发送client.on('messageReactionAdd')事件! 可能

有,但可能没有。但是,您一旦收到API响应,便立即开始侦听网关的响应。这就是所谓的竞赛条件-Discord负责REST API的服务器与它负责网关的服务器竞争,谁先将这些信息发送给您的机器人。

这不是您可以合理避免的事情,因为您绝对无法知道网关何时会赶上事件并向您的漫游器发送自己的反应-因此,您应该做的是考虑过滤器中的竞争状况:

messageReactionAdd

这只是忽略了您自己的漫游器的反应,因为它们永远都没有关系。比赛条件解决了! (无论如何这次)


[顺便说一句,我强烈建议使用function filter(reaction, user) { if(user.id == client.user.id) return false; console.log('reacted to: ', reaction.emoji.name); return true; } ,而不是那些难看且难以理解的承诺链。您的代码可以简化为:

async/await

应该与您当前的代码完全相同,但是我认为它更具可读性。

© www.soinside.com 2019 - 2024. All rights reserved.