async/await阻塞事件循环吗?

Moh*_*ziz 7 javascript asynchronous node.js promise async-await

我正在阅读Node.js指南中的" 不要阻止事件循环 ".有一句话说:

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

我开始想知道,如果一些API调用数据库我正在await花费一些时间来解决,这是否意味着我已经阻止了该await调用的事件循环?

之后,我开始测试一些自编代码,但经过测试后,我仍然不清楚阻塞是如何await工作的.以下是一些测试代码:

假设我正在使用express进行测试.我理解为什么/test在这种情况下对路由进行2次API调用会阻塞事件循环.

function someHeavyWork() {
  // like calling pbkdf2 function
}

app.get('/test', (req, res) => {
  someHeavyWork();
  res.json(data);
});
Run Code Online (Sandbox Code Playgroud)

但在这种情况下不会发生这种情况.

function fakeDBCall() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(data);
    }, 5000)
  })
}

app.get('/test', async (req, res) => {
  const data = await fakeDbCall();
  res.json(data);
})
Run Code Online (Sandbox Code Playgroud)

这可能是因为我缺乏对阻塞如何工作的理解async/await.

Li3*_*357 27

与它看起来相反,await不会阻止.这只是对承诺的语法糖.什么都没有阻止; 它可能看起来阻塞以允许代码同步,但这只是承诺的糖.例如,这可能看起来是同步的:

const response = await fetch(…);
const json = await response.json();
const foo = JSON.parse(json); // Using json here, even though my request was async!
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.一旦你去了它,你得到的都是承诺,这是非阻塞的:

fetch(…)
  .then(response => response.json())
  .then(json => {
    const foo = JSON.parse(json);
  });
Run Code Online (Sandbox Code Playgroud)

如果await阻止,那绝对是灾难性的.JavaScript运行时通常是单线程的.这意味着只要您发出请求或其他异步操作(例如使用文件系统),用户交互和其他进程就会停止.在相关的说明中,这与动态导入一起是反对顶级主要论据await

  • @MohammadAziz 在内部,`await` 执行 [PerformPromiseThen](https://www.ecma-international.org/ecma-262/9.0/index.html#sec-performpromisethen),这基本上就是 `Promise#then`。在操作中,一个【新的Job入队(带回调)】(https://www.ecma-international.org/ecma-262/9.0/index.html#sec-enqueuejob)。一旦调用堆栈为空,就会执行这些作业(因此,通过事件循环,一旦调用堆栈为空,就将新作业推送到调用堆栈中)。 (2认同)