Discord.js awaitReaction 在 message.react 收集反应后链式承诺,因为承诺未解决

2024-01-30

我正在玩message.react函数和awaitReactions https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=awaitReactions功能,我注意到一些让我困扰的事情。

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

  1. 发送消息
  2. 添加反应
  3. 每次添加反应时执行某些操作(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)}`);
    });
  });
}

Debug

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

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

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

But 有时(这取决于)它工作正常,日志如下:

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

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

所以我尝试了其他方法,我添加了 sleep 函数,它需要一定的毫秒数和一个值,并返回一个承诺,一旦经过毫秒数后解析,它将返回该值。 (取消注释第 3 行以进行此调试)。 这样收集者就永远不会收集到最后一个表情符号。

我也试图回报之前的承诺then与收集器(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;
}

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

note:
Node.js版本:v11.15.0
Discord.js 版本:v11.5.1


这是由于两者之间的分离REST APIGateway与 Discord 互动时。

在后台,message.react导致discord.js 向Discord 的REST API 发出请求 - Discord 将接收该请求、处理它并返回响应,这会导致由message.react解决或拒绝。

但是,当您监听反应时,它根本不是在监听 REST API,而是在监听网关事件- 这些很大程度上是导致诸如此类事件的原因client.on('messageReactionAdd')在客户端上发出。

当您收到来自不和谐的回复,表示您的反应已成功发布时,不和谐不一定已完成发送messageReactionAdd活动以了解您对所有客户端(包括您的机器人)的反应!它might有,但也可能没有。然而,您在收到 API 响应后立即开始监听来自网关的反应。这就是所谓的竞争条件- Discord 负责 REST API 的服务器正在与负责网关的服务器竞争,看谁会先将该信息发送给您的机器人。

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


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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Discord.js awaitReaction 在 message.react 收集反应后链式承诺,因为承诺未解决 的相关文章

  • AWS Lambda 提前结束(没有任何显式返回或回调)

    我在放入 AWS Lambda 中的一些 Node js 代码时遇到了一些问题 我需要进行几个异步调用 虽然第一个调用的行为符合我的预期 但 lambda 函数在第二个调用完成之前终止 返回值为 null 这让我认为 lambda 正在执行
  • Heroku ENOENT:没有这样的文件或目录,stat '/app/build/index.html'

    我在 Heroku 中运行一个简单的测试站点时遇到问题 由于某种原因 当我希望它从 build 提供服务时 它试图从 app build 提供内容 错误 ENOENT 没有这样的文件或目录 stat app build index html
  • npm 错误! cb.apply 不是函数

    我收到这个错误 npm ERR cb apply is not a function 在Linux中做的时候npm install虽然我的npm版本是6 9 0 我的节点版本是v12 18 3 如何解决这个问题 如果您共享的是 Window
  • 全局未在 ../node_modules/socket.io-parser/is-buffer.js 中定义

    预先感谢您帮助我 我正在尝试在我的一个角度组件中连接套接字 但在浏览器的控制台中它会抛出一个错误 指出 Global 未在 Object node modules socket io parser is buffer js 中定义 这是我的
  • 了解使用 Windows 本机 WPF 客户端进行 ADFS 登录

    我已经阅读了大量有关 ADFS 与 NodeJS Angular 或其他前端 Web 框架集成以及一般流程如何工作的文献 并通过 Auth0 Angular 起始代码构建了概念证明 但我不明白如何这可以与本机 WPF Windows 应用程
  • 以异步方式执行 Express res.render

    我有一个 Nodejs 应用程序 其中res renderExpress 方法以阻塞方式花费大约 400 毫秒 我如何处理它以非阻塞方式执行 我的 apache 基准测试需要 12 秒来执行大约 30 个并发请求 我如何以更好的方式实施这一
  • 使用 Promise 对 Google 表格进行多次查询

    我是一名初学者编码器 需要一些帮助来加快我的 Google 表格查询速度 我环顾四周 找不到解决方案 我正在尝试快速对 Google 表格运行 25 个查询 这就是我的尝试方式 对 Google 工作表运行查询 将结果推送到数组 运行不同的
  • Node.js:读取 URL 中传递的参数

    在 Rails 中 我向服务器发出 POST 请求 response Typhoeus Request post http url localtunnel com request from ola to ole result JSON pa
  • 在 mongodb 和 nodejs 中对博客和评级进行建模

    我有一个博客集合 其中包含用户给予的标题 正文和综合评分 另一个集合 评级 其架构引用了博客 以对象 ID 的形式对博客进行评级 如果有的话 的用户以及他们给出的评级 即 1 或 1 当特定用户按照 最新优先 的顺序浏览博客时 比如每页 4
  • 限制 Axios 请求

    我正在使用 axios 向 Deezer API 发出请求 不幸的是 使用 Deezer 的 API 当您请求艺术家的专辑时 它不包括专辑曲目 因此 我正在通过请求艺术家的专辑 然后对每个专辑执行后续的 axios 请求来解决这个问题 我遇
  • Nodemailer发送日历事件并将其添加到谷歌日历

    我正在尝试使用 nodemailer 将日历事件发送到 Gmail 帐户 这是我的代码 let transporter nodemailer createTransport host smtp gmail com port 587 secu
  • Node 不断恢复到旧版本

    每次我在控制台中重新启动 vagrant 时 它都会询问我的登录详细信息 然后说Now using node v7 10 0 npm v4 2 0 当我做run nvm install node I get v13 11 0 is alre
  • Javascript ES6 承诺支持“done”api 吗?

    例如 p new Promise function resolve reject throw err p done 在大多数 Promise Polyfill 库中 done 会抛出错误 并且当前执行将退出 但如果我们使用p then 什么
  • 将消息从 AWS Lambda 发布到 AWS IoT

    我正在尝试使用 Nodejs 将消息从 AWS Lamba 发布到 AWS IoT 我已压缩该项目并上传到 AWS IoT 下面是代码片段 var awsIot require aws iot device sdk var device a
  • 第一次使用node.js - “ReferenceError:节点未定义”

    我刚刚安装了node js 我尝试编写应该检查版本的node v 但它不起作用 这是输出 gt node v ReferenceError node is not defined at repl 1 2 at REPLServer self
  • GraphQL 预期可迭代,但未找到字段 xxx.yyy 的迭代

    我目前正在尝试使用 NodeJS 进行 GraphQL 但我不知道为什么以下查询会出现此错误 library name user name email 我不确定是否type of my resolveLibrary是对的 因为在任何例子中我
  • 如何使用 Chai Http 发布对象数组

    我正在尝试发布一个对象数组ChaiHttp https github com chaijs chai http像这样 agent post route to api send locations lat lat1 lon lon1 lat
  • 如何导入和导出 javascript ES6 类

    我是 javascript 和 nodejs 的新手 我正在使用这个项目来发展我的技能并学习新技术 目前我的项目使用多个相互依赖的类 类文件位于不同的目录中 我当前正在尝试使用 export 和 require 语句来允许在其他文件中引用类
  • 构建:找不到“节点”的类型定义文件

    VS 2015 社区版 在家 npm 3 10 Angular 2 我试图在 ASP Net MVC 5 应用程序中获取 Angular2 设置 我开始使用的模板使用旧版本的 Angular 因此我更新了包引用 当我构建时 列表中的第一个错
  • 一次更新猫鼬中的多个文档

    我有一个用户文档数组 每个用户都有关注者属性 它是一个数字 我只想将此属性增加 1 然后立即更新数据库中的所有这些用户文档 更多细节 在请求中 我有一组用户 id 我使用这些 id 进行查询以获取一组用户文档 const users awa

随机推荐