首页 > 解决方案 > 为什么我的回调函数接收到不正确的参数值?

问题描述

我有一个函数(称为 rankCheck),它接受三个参数:

  1. 公会对象(又名 Discord 服务器)
  2. 用户身份
  3. 回调函数

该函数将从提供的公会中的每个文本频道获取最后 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。为什么是这样?

标签: node.jsdiscord.js

解决方案


你的回调函数在你改变之前就被调用了sumOfRankChecksCollection#each(和Map#forEach()该帮派)不能等待Promise解决,因为它们的构建方式。无论如何,您的代码也不会等待,因为您没有使用await.

尽管人们可能认为正在发生什么,但它会guild.channels.each()被调用,并在之后立即callback()被调用。这是你困惑的根源。

有关异步与同步的更多信息,您可以在此处查看我的答案中的解释。您必须使用for循环和await,或重构您的代码,以便不需要 async/await 语法。


注意:超链接的 Discord.js 文档适用于最近发布的 v12。如果您的 Discord.js 不是最新的,请切换到页面顶部的正确版本以获取准确信息。


推荐阅读