我有这个问题,其中在返回路由器对象的路由器文件中 - 中间件在响应完成后被调用。
我认为在路线之后放置的中间件永远不会被执行 对于那条路线,我特别认为如果有回应就行 已经给了。
主要问题:
中间件应该在响应后停止被调用吗?
Ex:调用端点“/ login”并发送响应时 中间件A和B都被调用。
注意:我已将路由器包装在更高阶的功能中 (对于socket.io功能,但这不是重点)。
代码示例:
var express = require('express');
var router = express.Router();
var wrappedRouter = function(val) {
router.get('/login', function(req, res) {
console.log("Inside login route");
res.sendFile(path.resolve('login.html'))
}
router.use(function(req, res, next) {
console.log("Exectuing middleware A");
});
router.use(function(req, res, next) {
console.log("Exectuing middleware B");
});
router.get('/another-route', function(req, res) {
res.sendFile(path.resolve('login.html'))
}
return router;
}
//Prints:
// Inside login route
// Exectuing middleware A
// Exectuing middleware B
答案 0 :(得分:5)
你的假设是绝对正确的,如果你不打电话给下一个,链中的下一个中间件永远不会被执行,你所面临的问题是因为你已经猜到,由于你的页面正在请求静态资源,比如favicon或图像或任何其他(单独的请求)。要获得具体证据,您可以在提供明确请求时记录网址,并查看使用req.url
发出的请求和执行的内容,如下所示
var express = require('express');
var router = express.Router();
var path = require('path');
var wrappedRouter = function(val) {
router.get('/login', function(req, res) {
console.log("Inside login route: " + req.url);
res.sendFile(path.resolve('login.html'))
});
router.use(function(req, res, next) {
console.log("Exectuing middleware A: " + req.url);
});
router.use(function(req, res, next) {
console.log("Exectuing middleware B: " + req.url);
});
router.get('/another-route', function(req, res) {
res.sendFile(path.resolve('login.html'))
});
return router;
}
module.exports = wrappedRouter({});
在req.url
中注意console.log("Inside login route: " + req.url);
这将附加当前的req资源,我们将能够识别所调用的内容和原因。如下图所示
所以现在我们知道发生了什么以及为什么,现在让我们看看我们如何解决它。
在表达我们注册表达app的东西的顺序非常重要。我建议单独注册您的中间件(第一个),然后注册您的路由,这将增加您超级棒代码的可管理性!
话虽如此,由于序列很重要,在你的情况下发生了什么,表达顺序尝试每个中间件,直到它用完为止。因此,当服务器请求'favicon'(或其他一些静态资源)时,它会开始按顺序执行匹配的中间件。 “中间件A”处理请求并生成输出(请记住,不提供favicon,实际上没有任何操作,请求将继续处理,直到您下一次呼叫或发送响应内容。
您的问题的解决方案是在注册任何内容之前在app.js的开头注册一个静态文件夹。这样,当请求静态资源时,它们会立即被提供,静态资源中间件不能接受的其他请求会被传递到您的中间件。
不建议您提供服务文件,因为随着应用程序的增长,您可能会觉得难以管理,相反,您应该使用视图引擎/静态中间件来获得您想要实现的目标,如下面的代码所示
您的应用结构应如下所示,它将解决您的问题。
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//This will return wrapped routers
var routes = require('./routes/index');
var other = require('./routes/other');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
//Just after registering all request parsing middleware, register static middleware
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/others', other);
// 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
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
如果你是新手,想要开始并看看有什么用,我写了一篇关于它的小博客,第一部分已经完成,其余的都在排队;)
Get started with Express and build RESTful api 在这一部分中,我将展示如何搭建一个快速应用程序,代码来自它。你可能会发现它很有帮助。
希望它有所帮助!如果您还有其他需要,请告诉我们!
答案 1 :(得分:1)
Express正在按照您定义的顺序执行中间件,生命周期不会以res.send()
结束。
您可以使用它们,例如即使请求已经满足,也要进行后处理。
var wrappedRouter = function(val) {
router.use(function(req, res, next) {
request.startProcessingTime = +(new Date());
next();
});
router.get('/another-route', function(req, res) {
res.sendFile(path.resolve('login.html'))
}
(...)
router.use(function(req, res, next) {
req.endProcessingTime = +(new Date());
next();
});
router.use(function(req, res, next) {
console.log('Processing time:', req.endProcessingTime - req.startProcessingTime)
});
return router;
}
答案 2 :(得分:1)
我应该说的另一件事,请确保在next()
中调用router.use()
,如下所示。
router.use(function(req, res, next) {
console.log("Exectuing middleware A");
next();
});
router.use(function(req, res, next) {
console.log("Exectuing middleware B");
next();
});
router.get('/login', function(req, res) {
console.log("Inside login route");
res.send('Hello World');
});
哪个输出
Exectuing middleware A
Exectuing middleware B
Inside login route
如果next()
router.use()
router.use(function(req, res, next) {
console.log("Exectuing middleware A");
//next();
});
router.use(function(req, res, next) {
console.log("Exectuing middleware B");
//next();
});
router.get('/login', function(req, res) {
console.log("Inside login route");
res.send('Hello World');
});
输出:
Exectuing middleware A
此请求的浏览器中的响应正在等待...