node.js - 为什么我的回调函数接收到不正确的参数值?
问题描述
我有一个函数(称为 rankCheck),它接受三个参数:
- 公会对象(又名 Discord 服务器)
- 用户身份
- 回调函数
该函数将从提供的公会中的每个文本频道获取最后 500 条消息。然后它将只保留以“!rank”开头并由提供的 UserId 发送的任何消息。最后,它将计算剩余的消息并将整数传递给回调函数。
async function rankChecks(guild, userId = *REMOVED FOR PRIVACY*, callback){
sumOfRankChecks = 0;
guild.channels.cache.each(channel => { //for each text channel, get # of rank checks for userId in last 500 msgs.
if (channel.type === "text"){
fetchMessages(channel, 500).then(msgs => {
let filteredMsgs = msgs.filter(msg => msg.content.startsWith("!rank") && msg.member.user.id == userId);
sumOfRankChecks = sumOfRankChecks + filteredMsgs.length;
});
}
});
callback(sumOfRankChecks);
}
由于 discord 只允许一次获取 100 条消息,因此我使用此功能 (fetchMessages) 绕过此限制,通过发送多个请求,然后将结果合并为一个。
async function fetchMessages(channel, limit) {
const sum_messages = [];
let last_id;
while (true) {
const options = { limit: 100 };
if (last_id) {
options.before = last_id;
}
const messages = await channel.messages.fetch(options);
sum_messages.push(...messages.array());
last_id = messages.last().id;
if (messages.size != 100 || sum_messages >= limit) {
break;
}
}
return sum_messages;
}
当我调用 rankCheck 函数时,返回值始终为 0
rankChecks(msg.guild, *REMOVED FOR PRIVACY*, function(int){
console.log(int);
});
输出:
0
但是,当我将 console.log 添加到我的 rankCheck 函数中时:
async function rankChecks(guild, userId = *REMOVED FOR PRIVACY*, callback){
sumOfRankChecks = 0;
guild.channels.cache.each(channel => { //for each text channel, get # of rank checks for userId in last 500 msgs.
if (channel.type === "text"){
fetchMessages(channel, 500).then(msgs => {
let filteredMsgs = msgs.filter(msg => msg.content.startsWith("!rank") && msg.member.user.id == userId);
sumOfRankChecks = sumOfRankChecks + filteredMsgs.length;
console.log(sumOfRankChecks) //NEW CONSOLE.LOG!!!!!!!!!!!!!!!
});
}
});
callback(sumOfRankChecks);
}
输出:
3
5
这是我期待的输出。因为我的服务器中有 2 个文本通道,所以我有 2 个日志。如果你有 3 个通道,你会得到 3 个日志,等等。来自通道 #1 的 3 条消息,来自通道 #2 的 2 条消息,因此总共有 5 条消息。
5 应该是传递给回调函数的整数,但传递的是 0。为什么是这样?
解决方案
你的回调函数在你改变之前就被调用了sumOfRankChecks
。Collection#each
(和Map#forEach()
该帮派)不能等待Promise解决,因为它们的构建方式。无论如何,您的代码也不会等待,因为您没有使用await
.
尽管人们可能认为正在发生什么,但它会guild.channels.each()
被调用,并在之后立即callback()
被调用。这是你困惑的根源。
有关异步与同步的更多信息,您可以在此处查看我的答案中的解释。您必须使用for
循环和await
,或重构您的代码,以便不需要 async/await 语法。
注意:超链接的 Discord.js 文档适用于最近发布的 v12。如果您的 Discord.js 不是最新的,请切换到页面顶部的正确版本以获取准确信息。
推荐阅读
- ruby-on-rails - 设计运行不正常
- android - Android 片段:重叠 - 替换后仍然可见
- java - Java 虚拟受限存储(虚拟磁盘、映像、加密的 zip 文件等...)
- java - 如何在 Spring 中更改 Application.properties 的值
- gitlab - GitLab管道中`environment:url`使用的`CI_COMMIT_TAG`的字符串操作
- kubernetes - 在启动新 Pod 之前强制关闭 Kubernetes Pod,以防中断
- php - 使用对象作为键的多维地图
- python - TypeError:不支持的操作数类型 -=:python 上的 'slice' 和 'int'
- ios - 如何在ios swift中将新值添加到数组时实时更新tableview
- node.js - 使用快速身份验证对用户隐藏特定选项卡