- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在研究 message.react
函数和 awaitReactions
功能,我注意到一些困扰我的事情。
我试图确定是否应该为以下方法使用收集器或 client.on('messageReactionAdd')
(这是另一个问题):
所以我首先做了一个简单的示例,使用一个每次都返回 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 API 和Gateway 是分开的。
在后端,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/
如何从 promise 中退出 promise ? perl6 文档没有提供简单的方法。例如: my $x = start { loop { # loop forever until "qui
我的用户 Controller 中有一个索引操作,其中我试图连续做两件事,并且在它们都有机会完成之前不执行所需的 res.json() 方法。 我有一个加入用户的友谊加入模型。一列是 friender
请帮我解释一下为什么日志结果有两种不同: 方式 1:每 1 秒顺序记录一次 方式 2:1 秒后记录所有元素。 // Way 1 let sequence = Promise.resolve(); [1
我的问题很简单。 Promise.all() 方法可以返回 Promise 吗?让我解释一下: function simpleFunction() { let queue = [];
我正在使用 Promise 从存储中读取文件并转换为 base64 字符串。我有图像数组,使用 RNFS 读取图像 const promise_Images = _Images.map(async (
如果使用非空数组调用 Promise.all 或 Promise.race,它们将返回一个待处理的 Promise: console.log(Promise.all([1])); // prints
Promise.all 是否可以在没有包装 promise 的情况下返回链的最后一个值? 如果不使用 await,它在我的上下文中不起作用 没有包装的例子: function sum1(x){ r
我一直在玩 promise,通常能想出如何处理好它们,但在这种情况下,我不知道如何删除一个 promise-wrapping level。 代码如下: let promise2 = promise1.
考虑以下嵌套的Promises结构: const getData = async() => { const refs = [{ name: "John33", age: 3
我已经阅读了 Promise/A+ 规范,但据我了解,还有诸如 Promise/A 和 Promise 之类的东西。它们之间有什么区别? Promise 和 Promise/A 规范也是如此吗?如果是
当我运行以下代码时: my $timer = Promise.in(2); my $after = $timer.then({ say "2 seconds are over!"; 'result'
以下简单的 promise 是发誓的,我不允许打破它。 my $my_promise = start { loop {} # or sleep x; 'promise re
我正在尝试扩展Promise: class PersistedPromise extends Promise { } 然后在派生类上调用静态resolve以直接创建一个已解决的Promise: Per
我有两个返回 promise 的函数,我独立使用它们作为: getLocal().then(...) 和 getWeb().then(...) 但是现在我遇到了一个奇怪的问题: 1) 我需要第三个
我不知道 promise.all 解决方案中的 promise.all 是否是一个好的实践。我不确定。 我需要从一组用户获取信息,然后通过此信息响应,我需要发送消息通知。 let userList =
我一直在尝试使用 queueMicrotask() 函数,但我没有弄清楚当回调是微任务时回调的优先级如何。查看以下代码: function tasksAndMicroTasks() { const
我一直在尝试使用 queueMicrotask() 函数,但我没有弄清楚当回调是微任务时回调的优先级如何。查看以下代码: function tasksAndMicroTasks() { const
今年早些时候,我在 Pharo Smalltalk 参与了一个 promise 项目。这个想法是为了实现以下行为: ([ 30 seconds wait. 4 ]promiseValue )then:
大家好,提前感谢您的帮助。 下面是我正在尝试做的事情 function1(){ throw some error(); } function2() { // dosomething suc
我有以下未解析的代码。f2 解决了,所以我不会添加该代码,它是 f1 我有问题。 我调用函数,它到达最里面如果,它调用函数“find”,它执行函数 findId,完美返回 Id,然后执行 editId
我是一名优秀的程序员,十分优秀!