async/await 会阻塞一个线程 node.js [英] Will async/await block a thread node.js

查看:69
本文介绍了async/await 会阻塞一个线程 node.js的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在node.js函数中使用async/await时,会不会阻塞node.js线程直到执行下一行代码?

When async/await used in a node.js function, will it block the node.js thread untill it executes the next line of code ?

推荐答案

async/await 不会阻塞整个解释器.node.js 仍然以单线程方式运行所有 Javascript,即使某些代码正在等待 async/await,其他事件仍然可以运行它们的事件处理程序(因此 node.js 不会被阻止).事件队列仍在为其他事件服务.事实上,这将是一个解析承诺的事件,该承诺将允许 await 停止等待并运行以下代码.

async/await does not block the whole interpreter. node.js still runs all Javascript as single threaded and even though some code is waiting on an async/await, other events can still run their event handlers (so node.js is not blocked). The event queue is still being serviced for other events. In fact, it will be an event that resolves a promise that will allow the await to stop awaiting and run the following code.

代码如下:

await foo();            // foo is an async function that returns a promise
console.log("hello");

类似于:

foo().then(() => {
    console.log("hello");
});

因此,await 只是将该范围内的以下代码放入一个不可见的 .then() 处理程序中,其他所有内容的工作方式与实际编写时几乎相同使用 .then() 处理程序.

So, await just puts the following code in that scope into an invisible .then() handler and everything else works pretty much the same as if it was actually written with a .then() handler.

因此,await 允许您保存 .then() 处理程序的编写并为代码提供同步外观(尽管它不是真正同步).最后,它是一种速记,可让您用更少的代码行编写异步代码.确实需要记住,任何可以拒绝的承诺都必须在它周围的某个地方有一个 try/catch 来捕获和处理该拒绝.

So, await allows you to save the writing of the .then() handler and gives the code a synchronous look to it (though it isn't really synchronous). In the end it's a shorthand that lets you write async code with fewer lines of code. One does need to remember though that any promise that can reject must have a try/catch somewhere around it to catch and handle that rejection.

逻辑上,你可以想象 node.js 在执行函数时遇到 await 关键字的情况如下:

Logically, you can think of what node.js does when it encounters an await keyword when executing a function as the following:

  1. 进行函数调用
  2. 解释器看到函数被声明为 async,这意味着它总是会返回一个 promise.
  3. 解释器开始执行函数.
  4. 当它遇到 await 关键字时,它会暂停该函数的进一步执行,直到正在等待的承诺得到解决.
  5. 然后该函数返回一个未解决的承诺.
  6. 此时,解释器继续执行函数调用之后的任何内容(通常是 fn().then() 后跟其他代码行)..then() 处理程序尚未执行,因为 Promise 尚未解析.
  7. 在某些时候,这个 Javascript 序列完成并将控制权返回给解释器.
  8. 解释器现在可以自由地为事件队列中的其他事件提供服务.遇到 await 关键字的原始函数调用仍然暂停,但现在可以处理其他事件.
  9. 在未来的某个时刻,正在等待的原始承诺得到解决.当需要在事件队列中处理该事件时,先前挂起的函数会在 await 之后的行上继续执行.如果还有更多 await 语句,则函数执行将再次暂停,直到该承诺解决.
  10. 最终该函数命中一个 return 语句或到达函数体的末尾.如果存在 return xxx 语句,则对 xxx 进行求值,其结果成为此 async 函数已经拥有的承诺的已解析值回.该函数现在已完成执行,并且它先前返回的承诺已得到解决.
  11. 这将导致任何 .then() 处理程序附加到此函数之前返回的承诺上被调用.
  12. 在那些 .then() 处理程序运行之后,这个 async 函数的工作终于完成了.
  1. Function call is made
  2. The interpreter sees that the function is declared as async which means that it will always return a promise.
  3. The interpreter starts executing the function.
  4. When it encounters an await keyword, it suspends further execution of that function until the promise that is being awaited resolved.
  5. The function then returns an unresolved promise.
  6. At this point, the interpreter continues executing whatever comes after the function call (usually a fn().then() is followed by other lines of code). The .then() handlers are not executed yet because the promise is not yet resolved.
  7. At some point this sequence of Javascript finishes and returns control back to the interpreter.
  8. The interpreter is now free to serve other events from the event queue. The original function call that ran into an await keyword is still suspended, but other events can be processed now.
  9. At some future point, the original promise that was being awaited gets resolved. When it's time for that to get processed in the event queue, the previously suspended function continues executing on the line after the await. If there are any more await statements, then the function execution is again suspended until that promise resolves.
  10. Eventually the function hits a return statement or reaches the end of the function body. If there is a return xxx statement, then the xxx is evaluated and its result becomes the resolved value of the promise that this async function has already returned. The function is now done executing and the promise it previously returned has been resolved.
  11. This will cause any .then() handlers attached to the promise that this function previously returned to get called.
  12. After those .then() handlers run, the job of this async function is finally done.

因此,虽然整个解释器不会阻塞(其他 Javascript 事件仍然可以服务),但包含 await 语句的特定 async 函数的执行是暂停,直到正在等待的承诺解决.重要的是要理解上面的第 5 步.当第一个 await 被命中时,该函数立即返回一个未解析的承诺和代码,在该函数执行后(在 await 的承诺被解析之前).正是因为这个原因,整个解释器没有被阻塞.执行继续.只有一个函数的内部被挂起,直到一个 promise 被解决.

So, while the whole interpreter doesn't block (other Javascript events can still be serviced), the execution of the specific async function that contains the await statement was suspended until the promise that was being awaited resolved. What's important to understand is step 5 above. When the first await is hit, the function immediately returns an unresolved promise and code after this function is executed (before the promise being awaited is resolved). It's for this reason that the whole interpreter is not blocked. Execution continues. Only the insides of one function are suspended until a promise is resolved.

这篇关于async/await 会阻塞一个线程 node.js的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆