node.js 是否允许在没有任何等待/预期履行的情况下运行承诺?

All*_*ter 0 javascript node.js promise async-await discord.js

我喜欢浏览 Discord 标签并尽可能解决问题。我在 Python 方面相当流利,但在 Javascript 方面只能通过,但有时我确实把我的帽子扔到了戒指上。
Discord.py 库有许多必须等待的功能。否则将无法运行。
Discord.js 库为不同的事情返回了许多承诺,当我在写涉及这些的答案时,我很自然地添加了 await。我还查找了一个教程,以了解在 Discord.js 中编写 async/await 的最佳实践。
此外,添加 await 要求我使我的事件处理程序异步,这不合理地强化了我的信念,这些 await 语句需要存在。

client.on('message', async message => {
   await message.member.edit({mute: true})
});
Run Code Online (Sandbox Code Playgroud)

这一切都很好,而且我愚蠢地开始建议其他人也这样做。然而,在阅读问题和写答案时,我偶然发现了一些令我困惑的事情。

client.on('message', message => {
        let memberArray = [message.member];
        memberArray.forEach(member => member.edit({mute: true}));
        console.log("Do something after promised mute");
});
Run Code Online (Sandbox Code Playgroud)

这段代码没有异步函数也没有等待的承诺,仍然可以运行。这对我来说似乎很奇怪(如果代码可以执行,看起来是同步的,没有它,等待有什么意义?)。

继续混淆连续,我可以使这个函数异步并且仍然运行它而无需等待承诺。唯一会导致错误的是同步函数中的 await 语句。

另一种可能性是这不安全的并且会在生产中引起问题,但是由于我的测试机器人一次只与一个用户(我)交互,我看不到问题。Node.js 是否只是让我在没有警告的情况下运行糟糕的代码?我是否过度思考/过度设计了一个非问题?飞机餐是怎么回事?

jfr*_*d00 5

Javascript 中没有对await承诺的要求。如果你想进行一个异步调用,返回一个 promise 并在它完成时忽略,你可以这样做。这有时被称为“即发即忘”。我经常在关闭文件时这样做,例如因为当文件最终关闭时我没有任何用处。

需要从可能发生的承诺中捕获任何拒绝。因此,如果您的承诺有任何被拒绝的机会,您至少需要使用 a.catch()或 atry/catch围绕 an await

在这个特定的例子中:

client.on('message', async message => {
   await message.member.edit({mute: true})
});
Run Code Online (Sandbox Code Playgroud)

没有要求在await那里使用,事实上,它根本没有任何用处。它不会停止或暂停任何事情。如果message.member.edit({mute: true})返回一个promise,那么await它将暂停该回调的执行并立即将一个promise返回给触发该事件的事件系统,但nodejs中的其他事件将继续得到处理,无论如何这是函数​​中的最后一行,所以什么都没有实际上是通过await.

如果message.member.edit({mute: true})返回一个 promise 并且您想在回调中执行其他操作之前等待所有这些完成,那么您将必须使用for循环串行处理它们或并行处理它们并使用以下命令跟踪它们Promise.all()

// process serially with for loop and await  
client.on('message', async message => {
    try {
        let memberArray = [message.member];
        for (let member of memberArray) {
            await member.edit({mute: true});
        }
        console.log("Do something after promised mute is completed");
     } catch(e) {
        // catch any rejections
        console.log(e);
     }
});

// process in parallel with Promise.all()
client.on('message', async message => {
    try {
        let memberArray = [message.member];
        await Promise.all(memberArray.map(member => member.edit({mute: true})));
        console.log("Do something after promised mute is completed");
     } catch(e) {
        // catch any rejections
        console.log(e);
     }
});
Run Code Online (Sandbox Code Playgroud)

现在,如果member.edit({mute: true})不是异步的并且返回与异步操作相关联的承诺,那么所有这些都是没有意义的,因为await在任何情况下都不需要或有用。