Discord.js - Попытка одновременно дождаться асинхронного процесса и разрешить рекурсивные вызовы оболочки - PullRequest
0 голосов
/ 11 февраля 2019

У этого есть тонна движущихся частей, которые я пытался максимально упростить, и я все еще изучаю асинхронную / ожидающую обработку, так что терпите меня -

Так что я пытаюсьписать команды чата для чат-бота Discord с помощью discord.js.Команда, с которой у меня возникли проблемы, вызванная сообщением, начинающимся с !aut, должна принимать строку ввода пользователя (которая следует за самой командой) и возвращать другую строку;если пользователь не предоставляет строку, я хочу, чтобы он взял содержимое сообщения непосредственно над сообщением, содержащим команду (т. е. 2-ую самую последнюю), и использовал ее в качестве входной строки.

Однако, проверяя этоВ последнем случае он продолжает выдавать эту ошибку: (node:17896) UnhandledPromiseRejectionWarning: DiscordAPIError: Cannot send an empty message

Я структурировал бота с помощью прослушивателя событий, который прослушивает команды и вызывает функцию-оболочку execute(string, channel), если она обнаруживает;Оболочка затем вызывает соответствующую служебную функцию для этой команды, чтобы получить строку, которая затем возвращается обратно в прослушиватель, который затем отправляет строку в канал.

Функция полезности com_aut(array) работает отлично;проблема в том, что пустая строка по умолчанию sComResult, определенная в оболочке, возвращается слушателю, прежде чем она может быть перезаписана с помощью com_aut:

client.on('message', pMessage => {
    if (executable(pMessage.content) == true) {
        let sResult = execute(pMessage.content, pMessage.channel);
        pMessage.channel.send(sResult);
    }
});

function execute(sMessage, pChannel = null) {

    // strip off the initial ! that marks the message as a command; whatever comes immediately afterwards is the command
    let args = sMessage.substring(1).trim().split(/ +/g);
    let cmd = args[0];
    // don't include the command itself among the rest of the arguments passed to it
    args = args.splice(1);

    let sComResult = "";
    switch(cmd){

        ...

        case "aut":
            if (args.length < 1) {
                // input string that should be in args actually isn't, so grab the content of the 2nd most recent message instead
                pChannel.fetchMessages({ limit: 2 }).then(pMessages => {
                    sComResult = com_aut([pMessages.last().content]);
                });
            } else {
                // input string is present in args, so just use that
                sComResult = com_aut(args);
            }
            break;
    }
    return sComResult;
}

TextChannel.fetchMessages асинхронна - или возвращает обещаниепо крайней мере - поэтому я попытался сделать обертку также асинхронной, чтобы я мог принудительно установить ее на await.Плюс необходимые изменения в слушателе, я обнаружил, что это сработало:

client.on('message', pMessage => {
    if (executable(pMessage.content) == true) {
        execute(pMessage.content, pMessage.channel).then(sResult => { pMessage.channel.send(sResult) });
    }
});

async function execute(sMessage, pChannel = null) {

    // strip off the initial ! that marks the message as a command; whatever comes immediately afterwards is the command
    let args = sMessage.substring(1).trim().split(/ +/g);
    let cmd = args[0];
    // don't include the command itself among the rest of the arguments passed to it
    args = args.splice(1);

    let sComResult = "";
    switch(cmd){

        ...

        case "aut":
            if (args.length < 1) {
                // input string that should be in args actually isn't, so grab the content of the 2nd most recent message instead
                pMessages = await pChannel.fetchMessages({ limit: 2 });
                sComResult = com_aut([pMessages.last().content]);
                });
            } else {
                // input string is present in args, so just use that
                sComResult = com_aut(args);
            }
            break;
    }
    return sComResult;
}

Однако, СЕЙЧАС проблема в том, что я не могу вызвать execute(string, channel) рекурсивно, что я делаю, когда передаю выходные данные одной строки-output в другую команду ввода строки.(Именно поэтому обертка существует в первую очередь вместо того, чтобы прослушиватель просто связывался напрямую с служебными функциями). Это включает в себя execute вызов внутри самой execute.Я просто ссылку на pastebin на данный момент, но он выдает ошибку типа, так как он не может получить значение из вложенного execute и поэтому в итоге пытается вызвать null.then:

(node:6796) UnhandledPromiseRejectionWarning: TypeError: pInnerPromise.then is not a function

Как я могу структурировать мой код так, чтобы он должным образом ожидал запроса fetchMessages перед тем, как двигаться дальше, но все же разрешал рекурсивный вызов функции-оболочки (или каким-либо другим способом передачи)?

1 Ответ

0 голосов
/ 11 февраля 2019

Ваш код

    if (executable(sInnerCom) == true) {
   // here you are using await so promise is already resolved.     
    let pInnerPromise = await execute(sInnerCom, pChannel);
   // no need to use then, you can return result direct
        pInnerPromise.then(result => { sInnerComResult = result });
    }

Должно быть так

   if (executable(sInnerCom) == true) {
        let result = await execute(sInnerCom, pChannel);
         sInnerComResult = result ; 
    }

или вот так

if (executable(sInnerCom) == true) {
        sInnerComResult = await execute(sInnerCom, pChannel); 
    }
...