如何在JS(节点)中使用回调等待异步函数完成再继续?



我有一个名为translateCommand(command)的函数,它使用来自npm的翻译包将一些文本翻译成不同的语言。问题是该包提供的翻译函数是异步的,它倾向于在翻译函数完成之前退出 translateCommand 函数,从而导致返回垃圾数据。

我发现它完成得太快了,并将 translateCommand(command) 作为一个异步函数,这样我就可以在导入的 translate() 函数前面使用 await,这解决了这个问题,但现在我只是将问题推迟了一步,因为调用 translateCommand(command) 的函数遇到了完全相同的问题,我觉得如果我不得不继续重复这个,我没有任何进展链向上。

事实是,我真的不了解 Promise 以及 Async 函数与它们相关的一般行为。我意识到这是使 Node.js 变得伟大的前提,但试图了解它却相当无效。试图解决这个问题并没有真正取得成果,因为每个人都只是说使用回调,而没有解释回调到底是什么。这些示例通常被不熟悉的代码包围,这无济于事,所以我认为在我的代码上下文中获得帮助可以一石二鸟。

整个过程是我制作一个愚蠢的 Discord 机器人的介绍性尝试,我在其中实现了一堆愚蠢的功能。我多次遇到异步墙,但通常会找到一个同步替代方案来继续前进。这次我没有,我试图模拟其他 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 都是新手),我只能继续用头撞墙,直到有什么东西在我不明白的情况下起作用为什么。

您也可以将顶级函数更改为异步函数。将开头更改为async (message) => {并使用message.channel.send(await translateCommand(command))。或者,您可以选择使用 promise 而不使函数异步,而是使用translateCommand(command).then(msg => message.channel.send(msg)),但它可能会在代码后面弄乱流程。

因为translate返回一个承诺,所以你不需要translateCommandasync。只需从函数返回translate...

function translateCommand(command) {
let str = command.substr(10);
return translate(str, { to: 'ja', engine: 'yandex', key: '<my key>' });
}

。并await解决的承诺。您需要向事件处理程序回调添加asyncawait才能正常工作。

client.on("message", async (message) => {
let command = (message.content).substr(1);
//...
else if (command.startsWith("translate"))
message.channel.send(await translateCommand(command));
// ...
}
});

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

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)
})
// ...
}
});

如果您在语法方面遇到问题,这里有提示:
提示 #1
提示 #2
+ 一句话 - 不要害怕,花时间阅读 + 实现上述示例并在之后修改它们以导致错误(您将知道如何以及何时工作或不起作用 - 痛苦但有益的;)

)

最新更新