javascript - NodeJS 中的阻塞与非阻塞
问题描述
我们都知道 NodeJS 是单线程的,这意味着如果我们的代码中有 async/await 操作,节点会在执行其余代码之前等待它完成。因此,如果用户发出异步请求,其他用户也应该在发出请求之前等待它完成吗?
这里我创建了一个简单的示例,第一个路由使用异步函数,发送响应前需要 10 秒,第二个路由立即发送响应。
当我向第一个路由发送请求并等待响应时,我向第二个路由发送了另一个请求,即使第一个路由尚未完成执行代码,我也收到了响应。
为什么在这个例子中它是非阻塞的?
function sleep(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(true)
},10000)
}).then(val=>val)
}
router.get('/route1',async (req,res)=>{
const test = await sleep()
res.send('HELLO WORLD')
})
router.get('/route2',(req,res)=>{
res.send("HELLO WORLD")
})
解决方案
await
仅阻止/暂停当前函数的执行,而不是整个解释器。事实上,当一个函数命中await
函数内部的第一个函数时,该函数立即返回一个 Promise,并且在该函数(或发生的其他事件)可以自由运行之后的其他处理。
因此,在您的示例中,当它命中时await sleep()
,该函数执行将暂停,直到await
解析/拒绝并且包含async
函数立即返回一个未实现的承诺。由于 Express withrouter.get()
没有对返回的 Promise 做任何事情,它只是忽略它并将控制权返回给事件循环。稍后,您的第二个请求到达服务器,一个事件被放入 nodejs 事件队列,Express 被该事件调用,它为您的第二个路由处理程序提供服务。
因此,如果用户发出异步请求,其他用户也应该在发出请求之前等待它完成吗?
不。只有包含 的那个请求处理程序的一个实例await
被挂起。通过事件循环在解释器和其他事件处理程序中的其他执行(例如其他传入请求)仍然可以发生,因此仍然可以处理其他请求,即使一个请求处理程序位于await
. 这说明了如何await
不阻塞或暂停整个解释器,只执行一个函数。
当我向第一个路由发送请求并等待响应时,我向第二个路由发送了另一个请求,即使第一个路由尚未完成执行代码,我也收到了响应。为什么在这个例子中它是非阻塞的?
只有第一条路线被await
. 其他事件和其他传入请求仍然可以正常处理。
推荐阅读
- psycopg2 - 通过 psycopg2 连接到 CloudSql
- python - 是否可以在 BeautifulSoup4 中遍历 HTML-tree?
- python - 用零或字符串替换字典值中的所有整数
- typescript - jupyter笔记本中的打字稿
- python - 如何从 Python 启动 GUI 程序,但在用户关闭窗口时结束进程?
- html - 当有人访问您的静态网站时如何删除 .html
- typescript - 对象冻结文字对象类型
- html - 修复 rtl bootstrap 导航栏目录
- javascript - Node.js 和 Zaproxy UnhandledPromiseRejectionWarning: RequestError: Error: socket hang up
- php - 正则表达式数字,如 1.1k