首页 > 解决方案 > async/await 会阻塞事件循环吗?

问题描述

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

你应该确保你永远不会阻塞事件循环。换句话说,您的每个 JavaScript 回调都应该快速完成。这当然也适用于你await的,你Promise.then的,等等。

我开始想,如果对我正在await处理的数据库的某些 API 调用需要一些时间来解决,这是否意味着我已经用该await调用阻塞了事件循环?

之后,我开始测试一些自己编写的代码,但测试后我仍然不清楚阻塞是如何await工作的。下面是一些测试代码:

假设我正在使用 express 进行测试。我理解为什么在这种情况下对路由进行 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);
})

这可能是因为我对阻塞在async/await.

标签: javascriptnode.jsasynchronouspromiseasync-await

解决方案


与看起来相反,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 运行时通常是单线程的。这意味着只要您发出请求或其他异步操作(例如使用文件系统),用户交互和其他进程就会停止。在相关的说明中,这与动态导入一起是反对顶级的主要论据await


推荐阅读