我对使用Express和中间件进行异步调用有一个基本的误解,我非常感谢能帮助理解它的人。
假设我们有以下代码:
var express = require('express')
var cookieParser = require('cookie-parser')
var app = require('express')
var router = express.Router()
app.use(function timeLog (req, res, next) {
req.requestTime = Date.now()
next()
})
app .use(express.json());
app .use(express.urlencoded());
app.use(cookieParser())
router.post('/hello', function (req, res) {
//write async to file
res.send('bye')
})
现在,当客户端将该端点称为“ hello”时:
在应用程序级别定义的中间件称为异步吗?我知道它们会这样做(因为在文档中它们被称为“回调” ...因此基本上是在到达路由器之前:解析cookie,将json解析为req.body并添加req.requestTime将异步运行,然后路由至“ / hello的终点。
路由后,回调将异步运行吗?如果是,那么在这种情况下如何不保留请求?我看到响应已在回调主体中终止...这有什么意义? :(
有人请向我解释一下这个流程吗?
我将尝试通过上面的代码解释我如何理解“异步调用”:让很多用户尝试获得此终点。所有这些调用都添加到了调用堆栈中,然后由于这些回调是异步的,因此它们被移到事件队列/表中,并在调用堆栈为“空”之后进行处理。如果是这样,第一个用户将如何获得响应? requestTime完成异步,解析json完成异步,并在到达路由器时,回调完成异步...。因此,如果所有这些异步调用都位于事件Queue / table中,则第一个用户将获得代表。只有在调用栈为空后才能处理?我在这里想念什么?
谢谢。
答案 0 :(得分:1)
中间件似乎不是自己异步的。换句话说,正如您在对另一个答案的评论中所说的那样,这不是不将中间件/处理程序的expressjs“堆栈”中的每一层都强制放入JavaScript事件队列中的单独框架中。
如果您在next()
中跟踪.use()
函数,则很早就有几个setImmediate
来处理“出口路由器”或“没有更多的层”,但是您会在处理程序堆栈上进入while
循环。这发生在this point in the code附近。
因此,如果您所有的中间件都与本节类似,则所有中间件等都将在事件队列中的同一帧中发生:
app.use(function(req, res, next){
console.log('synchronous layer');
next();
});
下一个步骤是将next
放入事件队列中的单独帧中,并有可能允许该进程处理可能排队的其他帧。
app.use(function(req, res, next){
setImmediate(()=> {
console.log('setImmediate puts this next() into a separate frame in the event queue');
next();
});
});
我无法想象这通常是一个问题。在中间件中可能要花费一些时间(数据库调用等)的大多数事情很可能都是异步发生的(将next
放入事件队列的新帧中)。但这在添加中间件时值得考虑...
答案 1 :(得分:0)
所有这些中间件都使用延续传递样式。因此,基本上,它们可以异步运行。但是他们不必这样做。这取决于这些中间件是否正在执行某些IO。您可以看一下代码来检查函数的行为,但是至少这无关紧要。请记住,它们可以异步运行。