如何在JS(节点)中使用回调来等待Async函数完成才能继续?

时间:2019-04-30 22:21:39

标签: javascript node.js async-await discord.js async.js

我有一个名为translateCommand(command)的函数,该函数使用npm中的Translate包将某些文本翻译成另一种语言。问题在于该程序包提供的转换函数是异步的,并且倾向于在转换函数完成之前退出translateCommand函数,从而导致垃圾数据的返回。

我发现问题的解决速度太快了,并把translateCommand(command)设为了异步函数,因此我可以在导入的translate()函数前使用await,从而解决了该问题,但是现在我只是延迟了一下这个问题又往后退了一步,因为调用translateCommand(command)的函数遇到了完全相同的问题,而且我觉得如果我不得不继续向上重复此链,那我就没有取得进展。

事实是,我不太了解Promises以及Async函数相对于它们的一般行为。我意识到这是使Node.js变得更好的前提,但是尝试了解它却没有效果。尝试解决此问题并没有真正取得成果,因为每个人都只是说使用回调而没有解释确切的回调是什么。这些示例通常被陌生的代码包围着,这无济于事,所以我认为在代码的上下文中获得帮助将用两只石头解决两只鸟。

这是我做一个愚蠢的Discord Bot的介绍性尝试,我在其中实现了许多愚蠢的功能。我已经遇到过Async墙很多次了,但通常会找到一个Synchronous替代方法来继续前进。这次我没有这样做,我尝试模拟其他Stack Overflow帖子中描述的回调,但是由于缺乏理解,因此无法正确集成它们(我只能假设)。

现在具有异步问题的顶级导入函数。

client.on("message", (message) => {

    // ...
    let command = (message.content).substr(1);

    // ...

    // Handles translate command
    else if (command.startsWith("translate"))
        message.channel.send(translateCommand(command));

    // ...
    }
});

已设为异步状态以便可以等待的功能:

// Form !translate [string]
async function translateCommand(command) {
    let message = "";
    let str = command.substr(10);

    await translate(str, { to: 'ja', engine: 'yandex', key: '<my key>' }).then(function(result) {
        message = result;
        return "";
    });
    return message;
}

我知道这个问题已经死了,但是我感到如果没有上下文,我就会理解(因为我仍然对JS和Node还是陌生的),我只能在墙上碰头直到出现某种情况在我不了解原因的情况下工作。

3 个答案:

答案 0 :(得分:1)

您也可以将顶级功能更改为异步。将开头更改为async (message) => {,然后使用message.channel.send(await translateCommand(command))。另外,您可以选择使用Promise而不是使函数异步,而是使用translateCommand(command).then(msg => message.channel.send(msg)),但是稍后可能会扰乱代码中的流程。

答案 1 :(得分:0)

因为translateCommand返回一个诺言,所以您无需做出async translate。只需从函数返回function translateCommand(command) { let str = command.substr(10); return translate(str, { to: 'ja', engine: 'yandex', key: '<my key>' }); } ...

await

...和async解决的诺言。您需要将await添加到事件处理程序回调中,client.on("message", async (message) => { let command = (message.content).substr(1); //... else if (command.startsWith("translate")) message.channel.send(await translateCommand(command)); // ... } }); 才能正常工作。

def always_upcase_strings(&block)
  anon_class = Class.new do
    def puts(str)
      super(str.upcase)
    end
  end
  anon_class.new.instance_eval(&block)
end

always_upcase_strings do
  puts "abc" #=> "ABC"
  puts "def" #=> "DEF"
  puts "ghi" #=> "GHI"
end

puts "xyz"   #=> "xyz"

答案 2 :(得分:0)

使用诺言,您可以执行以下操作:

translateCommand函数:

var translateCommand = (command) => new Promise((resolve,reject) =>  {
    translate(command.substr(10), { to: 'ja', engine: 'yandex', key: '<my key>' })
        .then(resolve)
        .catch(reject)
    });

然后client.on

client.on("message", (message) => {

    // ...
    let command = (message.content).substr(1);

    // ...

    // Handles translate command
    else if (command.startsWith("translate"))
        translateCommand(command)
            .then(translationResult => {
               message.channel.send(translationResult)
            })
    // ...
    }
});

如果您对语法有疑问,请参阅以下提示:
hint #1
hint #2
+一句话-不要害怕,花时间阅读+实施以上示例,然后对其进行修改,以引起错误(您将知道它们何时以及如何起作用或不起作用-痛苦但有回报;))