【发布时间】:2021-04-05 05:32:50
【问题描述】:
据我了解,await 背后的意义在于“等待”对承诺的已解决值采取行动,直到它作为微任务遇到,正如 Jake Archibald 解释的 here。
This video by LLJS 表明 async-await 本质上是生成器运行器/解释器函数的语法糖,它产生它等待的位置并将承诺的确定值传递给 .next() 方法。这意味着当等待发生时,运行器对.next() 的执行将作为微任务排队。
实际上,await 下的所有代码只会在下一个微任务检查点执行。如果不需要等待的承诺值的代码位于其下方,这可能是一个问题,这正是 Async IIFE 的问题。
async function ping() {
for (let i = 0; i < 5; i++) {
let result = await Promise.resolve("ping");
console.log(result);
}
console.log("Why am I even here?");
}
async function pong() {
for (let i = 0; i < 5; i++) {
let result = await Promise.resolve("pong");
console.log(result);
}
console.log("I have nothing to do with any of this");
}
console.log("Let the games begin!");
ping();
pong();
console.log("Placeholder for code that is not related to ping pong");
在此示例中,首先记录外部日志作为运行脚本任务的一部分,然后按照它们在微任务队列中排队的顺序记录已解决的承诺的值。在整个过程中,for 循环下面留下的日志与循环无关,会不必要地暂停,直到各自函数体中的最后一个微任务出队列。
这正是我们使用 async 函数作为 IIFE 时发生的情况。如果您在await 下有旨在同步执行的代码,则它必须不必要地等待,直到它上面的所有等待都已从微任务队列中检出。
如果有人盲目地将他们的整个快速路由包装在async 函数中,我可以看到这是一个问题,在那里他们将不必要地await 解决某些承诺,如数据库操作、发送电子邮件、读取文件等...,那么为什么人们仍然这样做呢?
app.post('/forgotPwd', async (req, res) => {
const {email, username} = req.body;
if (!email) {
res.status(400).json({error: "No username entered"});
return;
}
if (!username) {
res.status(400).json({error: "No email entered"});
return;
}
const db = client.db();
const user = await db.collection("Users").findOne({username: username, "userInfo.email": email});
if (!user) {
res.status(400).json({error: "Account not found"});
return;
}
const authToken = await getAuthToken({id: user._id.toHexString()}, "15m");
// Would probably send a more verbose email
await sgMail.send({
from: process.env.EMAIL,
to: email,
subject: 'Forgot Password',
text: `Use this url to reset your password: http://localhost:5000/confirmation/passConf/${authToken}`,
});
res.json({error: ""});
});
【问题讨论】:
-
次要术语说明:您的意思是解决(拒绝或履行)或履行,而不是解决。一个承诺可以解决,但仍处于待处理状态。
-
我不会称该代码为无用,如果作者的意思是立即执行该部分,我只会称它为错误。跨度>
-
“如果有人盲目地将他们的整个快速路由包装在异步函数中” - 你能举一个具体的例子吗?我不确定你指的是什么。
-
感谢您添加示例,但您认为该代码的哪一部分与异步调用无关,应该立即完成?
-
@Clever7- 当然你需要等待!它可能会拒绝,在这种情况下需要发送错误响应,因此您无法在数据库事务完成之前发送响应。 (诚然,您展示的代码中缺少正确的错误处理,但这不是借口)。
标签: javascript async-await event-loop