Express:一旦做出响应,中间件是否应该停止调用?

Nic*_*eda 2 node.js express

我有这个问题,在路由器文件中返回一个路由器对象 - 中间件在响应已经被调用后被调用.

我认为在路线之后放置的中间件永远不会为该路线执行,我特别认为如果已经给出了响应,那将是真的.

主要问题:

中间件应该在响应后停止被调用吗?

例如:当调用端点"/ 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
Run Code Online (Sandbox Code Playgroud)

Dav*_*mit 6

你的假设是绝对正确的,如果你不打电话给下一个,链中的下一个中间件永远不会被执行,你面临的问题是,因为你已经猜到,由于你的页面正在请求的静态资源,如favicon或图像或其他任何事情(单独请求).要获得具体证据,您可以在提供快速请求时记录URL,并查看请求的内容以及执行的内容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({});
Run Code Online (Sandbox Code Playgroud)

请注意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;
Run Code Online (Sandbox Code Playgroud)

如果你是新手表达并想要开始并看看它是如何工作的,我写了一篇关于它的小博客,第一部分已经完成,其余的都在排队;)

开始使用Express并构建RESTful api 在这一部分中,我将展示如何构建一个快速应用程序,代码来自它.你可能会发现它很有帮助.

希望能帮助到你!如果您还有其他需要,请告诉我!