下面是我的代码,它有两个回调和一个获取路径
app.get('/login', function(req, res, next) {
res.sendFile(__dirname + '/public/views/login.html');
});
app.use(function (req, res, next) {
console.log("first callback 1");
var err = new Error('Not Found');
err.status = 404;
next(err);
console.log("first callback 2");
});
app.use(function (err, req, res, next) {
// set locals, only providing error in development
console.log("second callback");
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
console.log("error send");
});
基本上这里有两个回调用于错误处理。如果我运行应用程序并转到localhost:3000/home
,因为没有路由,并且由于回调,我得到404错误。
但是如果我转到localhost:3000/login
,它会显示我的login.html页面,但没有调用回调。即使没有错误我的意思是至少它应该在回调中打印第一个控制台消息。但是为什么不调用回调?
我读到的关于回调的内容是,如果你没有指定任何路径,它会被调用所有路径。但为什么不在这里?有人花时间阅读这个并清除我,如果我错了。
答案 0 :(得分:2)
这与回调无关。它是关于中间件(插件/模块)体系结构如何在Express中工作(以及顺便说一下其他许多框架,但要注意:并非所有框架都像这样工作)。
Express实现的真正代码是模块化的,有点复杂,但基本上它的工作原理如下:
var middlewares = [];
var app = {
use: function (callback) {
middlewares.push({path:"", callback: callback});
},
get: function (path, callback) {
middlewares.push({path: path, callback: callback});
}
}
所以你看,这个想法很简单。真的没什么特别的。 .use()
用于添加要对所有路径执行的代码,.get()
用于添加路径匹配时要执行的代码。
因此,我们现在可以通过遍历数组来处理每个请求到服务器:
// WARNING: NOT REAL CODE, this is only meant as an illustration
function processRequest (req, res) {
for (var i=0; i<middlewares.length; i++) {
var whatToDo = middlewares[i];
if (whatToDo.path == "") { // no need to check path
whatToDo.callback(err, req, res, next);
}
else if (whatToDo.path == req.path) { // check if path match
whatToDo.callback(req, res, next);
}
}
}
这就是它的工作原理。当然,中间件是异步的,因此在实际代码中我们不能使用for循环。这实际上是next()
函数的用途 - 循环中间件,如链表(仅限链接函数)。如果没有调用next()
,则循环停止。