为什么这个node.jscallback没有立即运行?

使用express-generator它会吐出一些像这样的error handling代码:

 app.use('/', routes); app.use('/users', users); // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // error handlers // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); } 

在这个例子中,如果(无论出于何种原因)我的路由被破坏或者找不到路由或者其他什么的,代码就会退回到第二个代码块中。 在第二个代码块(404处理程序)开始执行后,第三个代码块(500处理程序)如何不立即执行?

我认为node.jscallback的工作方式是函数开始执行,并继续在后台执行,然后下一个callback开始同时开始执行。 但显然,我是如何同步callback工作有点困惑。 在运行500error handling程序之前,上述代码是否知道“等待”404处理程序代码完成执行?

所有的app.use()语句都会在您的应用初始化时运行。 他们每个人都build立了一个“中间件”处理程序。 他们当时并没有真正运行处理程序,只是将它们注册到Express中间件堆栈中。 如果之前的处理程序没有处理页面,那么这两个最后的app.use()中间件处理程序将按顺序发送请求,第二个只有在第一个请求传递给更多的处理程序时才会看到请求。

404处理程序将状态设置为404 ,然后调用中间件堆栈中的next()处理程序。 这将最终成为你的最后一个app.use()语句,看看是否已经设置了一个状态,如果没有,将设置为500 ,但如果它以前设置为404 ,它将离开它。 然后,它将应用缺省页面的默认渲染,以显示页面中的状态。

这是一种将单个地方应用默认渲染的方法,但是可以设置多个错误的地方。

这些与asynchronous行为没有任何关系。 列表中的下一个请求处理程序只有在先前的请求处理程序调用next()时才会启动。 没有“等待”。 你可以使用最后一个app.use()语句来调用404请求处理程序,就像调用next()时的同步函数调用一样,它只是说请执行链中的下一个请求处理程序(这正好是知道的为错误状态代码提供默认呈现的那个)。


查看app.use()如何在Express中工作可能会有帮助。

每次调用app.use()将一个请求处理程序添加到列表中。 当一个给定的http请求进入时,Express从列表中的第一个请求处理程序开始,并检查列表中第一个请求处理程序的参数是否与当前请求相匹配(例如path是否匹配或者app.use()语句)。 如果匹配,则调用该请求处理程序。 如果请求处理程序没有调用next()来让列表中的下一个请求处理程序有请求的机会,那么所有的处理都完成,并且Express假定第一个请求处理程序已经完全处理了请求。 如果这个第一个请求处理程序没有完全处理请求(比如说只是在头文件中检查一个cookie值,并且想要继续处理其他的处理程序),那么它将调用next() 。 这告诉express看看列表中的下一个app.use()处理程序,看看它是否匹配这个请求。

只要没有请求处理程序匹配当前请求,或者每个请求处理程序都继续调用next()以保持链接,Express将继续向下寻找请求处理程序来处理请求并生成服务器响应。 在您的具体示例中,链中的第二个请求是404处理程序。 它假设如果Express得到了这个链,那么没有处理程序还没有处理这个请求,所以它必须是一个请求这个服务器没有devise处理的页面。 因此,它将状态设置为404.然后,因为错误页面的默认呈现位于最后一个请求处理程序中,它将调用next()以触​​发最后一个带有错误的默认页面呈现。


解释器中只有一个线程正在运行你的代码。 I / O操作是并发执行的,这样JS执行就可以继续而不会阻塞I / O。 这称为asynchronous,因为callback执行的时间和顺序不在您的直接控制之下。 两个JavaScript函数不能同时执行。

上面的代码将在没有执行任何callback函数的情况下运行。 代码运行后, http模块将监听客户端请求(通常,您没有在上面显示)。 这些callback将根据需要执行以响应这些客户请求。 他们不是一直在单独的线程中运行,而是在等待数据。 app.use只是在express中间件堆栈中注册函数。 当请求与您指定的路由匹配时(或不是),将按顺序调用适用的callback。 这就是为什么你必须在你的中间件中调用next 。 如果你不这样做,请求对象的处理停止(这个devise被称为连续传递样式 )。

这些函数执行的确切顺序并不为您所知,并不重要。 只有相对的顺序很重要,即哪两个函数会先被调用。 通常,代码结构将保证这一点(即为I / O调用提供callback函数)。 这意味着解释器能够立即处理每个I / O活动的结果,而不必担心线程pipe理等。