我正在阅读Node.js指南中的Don't Block the Event Loop。有一句话说:
您应该确保您永远不会阻止事件循环。换一种说法, 您的每个JavaScript回调都应快速完成。这个 当然也适用于您的
await
,Promise.then
等。
我开始怀疑,如果我正在await
正在对数据库进行一些API调用要花费一些时间来解决,那是否意味着我已经用{{1}阻止了事件循环? }致电?
此后,我开始测试一些自行编写的代码,但是在测试之后,我仍然不清楚通过await
进行阻止的工作方式。以下是一些测试代码:
假设我正在使用Express进行测试。我了解为什么在这种情况下对await
路由进行2次API调用会阻止事件循环。
/test
但是在这种情况下不会发生。
function someHeavyWork() {
// like calling pbkdf2 function
}
app.get('/test', (req, res) => {
someHeavyWork();
res.json(data);
});
这可能是因为我对function fakeDBCall() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data);
}, 5000)
})
}
app.get('/test', async (req, res) => {
const data = await fakeDbCall();
res.json(data);
})
情况下的阻塞工作原理缺乏了解。
答案 0 :(得分:18)
与看起来相反的是,await
不会阻止。只是对诺言的 句法糖 。没有任何障碍;它看起来似乎很阻塞,以允许代码同步,但这仅是对承诺的保证。例如,这可能看起来是同步的:
const response = await fetch(…);
const json = await response.json();
const foo = JSON.parse(json); // Using json here, even though my request was async!
但是不是。脱糖后,您得到的只是诺言,而诺言是无障碍的:
fetch(…)
.then(response => response.json())
.then(json => {
const foo = JSON.parse(json);
});
如果await
被阻止,那将是绝对的灾难。 JavaScript运行时一般是 单线程。这意味着,无论您何时发出请求或其他异步操作(例如使用文件系统),用户交互和其他进程都将停止。与此相关的是,这与动态导入一起是main argument against top level await
答案 1 :(得分:2)
await不会不阻塞事件循环。实际上,当javascript看到您的await
时,它将立即将控制权移交给事件循环。
答案 2 :(得分:0)
异步函数返回一个Promise,并且您正在传递请求和响应,我将更改 res.json(数据) 至 返回res.json(data)
当异步函数返回值时,promise将被解析,如果该函数包含错误,则仅出于清洁目的而拒绝promise,返回res.json(data)将解析该函数。