异步/等待阻止事件循环吗?

时间:2018-07-29 18:48:58

标签: javascript node.js asynchronous promise async-await

我正在阅读Node.js指南中的Don't Block the Event Loop。有一句话说:

  

您应该确保您永远不会阻止事件循环。换一种说法,   您的每个JavaScript回调都应快速完成。这个   当然也适用于您的awaitPromise.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); }) 情况下的阻塞工作原理缺乏了解。

3 个答案:

答案 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)将解析该函数​​。