路由后的 Node Express 4 中间件

Posted

技术标签:

【中文标题】路由后的 Node Express 4 中间件【英文标题】:Node Express 4 middleware after routes 【发布时间】:2014-08-07 04:03:16 【问题描述】:

在升级到 Express 4 并删除 app.router 之后,我正在努力让中间件在路由执行后执行。

例如以下代码正确响应“hello”,但从不调用配置的中间件

var express = require( "express" )();

express.get( "/", function( req, res ) 

    res.send( "hello" );

 );
express.use( function( req, res, next ) 

    console.log( "world" );
    next();

 );

express.listen( 8888 );

澄清:

以下代码在控制台上显示“之前”,而不是“之后”:

var express = require( "express" )();

express.use( function( req, res, next ) 

    console.log( "before" );
    next();

 );
express.get( "/", function( req, res ) 

    res.send( "hello" );

 );
express.use( function( req, res, next ) 

    console.log( "after" );
    next();

 );

express.listen( 8888 );

【问题讨论】:

为我工作。什么不适合你。 我从来没有看到 console.log 输出 在 node.js 命令行中为我显示。你有额外的代码吗? 不,就是这样。你运行的是什么版本的快递? (我在 4.4) 我的是 4.4.3。试试看。 【参考方案1】:

顺序很重要http://expressjs.com/4x/api.html#app.use

express.use( function( req, res, next ) 
  console.log( "world" );
  next();
);
express.get( "/", function( req, res ) 
  res.send( "hello" );
);

【讨论】:

是的,但这是错误的顺序。我希望我的中间件在路由处理程序之后执行。【参考方案2】:

您是否检查过将您的 console.log 放在 next() 调用之后?

express.use( function( req, res, next ) 
  next();
  console.log( "world" );
);
express.get( "/", function( req, res ) 
  res.send( "hello" );
);

【讨论】:

它看起来像一个健壮的变种。 如果请求执行任何异步操作,这将无法正常工作【参考方案3】:

关于 Express 4,第二个示例中的“after”函数永远不会被调用,因为中间函数永远不会调用 next()。

如果您希望调用“after”函数,则需要从中间函数添加并调用下一个回调,如下所示:

var express = require( "express" )();

express.use( function( req, res, next ) 
  
  console.log( "before" );
  next();
  
 );
express.get( "/", function( req, res, next ) 

  res.send( "hello" );
  next();      // <=== call next for following middleware 

 );
express.use( function( req, res, next ) 

  console.log( "after" );
  next();

 );

express.listen( 8888 );

res.send() 将标头和响应写回客户端。

请注意,一旦调用了res.send(),您就不想更新响应标头或内容。但是您可以执行其他任务,例如数据库更新或日志记录。

请注意,express 查看中间件函数中参数的数量并执行不同的逻辑。以express error handlers为例,它定义了4个参数。

表达错误处理程序签名:

app.use(function(err, req, res, next) );

对中间件链中的最后一项调用 next 是可选的,但如果你改变了事情,这可能是一个好主意。

【讨论】:

现在是真的。大多数 express 示例的路由在处理函数中指定为 2。但是这样做会阻止添加应该在处理路由后执行的中间件。这对他们来说似乎是一个奇怪的约定。【参考方案4】:

正确答案是使用res.on("finish", cb) 回调。

即:

express.use(function(req, res, next) 
    console.log("before");

    res.on("finish", function() 
        console.log("after");
    );

    next();
);

【讨论】:

这家伙说的是“res.once”,而不是“res.on”lunchbadger.com/… @datdinhquoc 这并不重要,因为在 Express 处理完响应对象后 res 将不可用,因为每个请求都会导致新的 reqres 对创建(由 Express)。你是对的,通常负责任的开发人员应该做的,但在这种特殊情况下,它们是相同的。 @Catfish 这是使用节点的http 模块response 功能node docs。正如您将在express docs 中看到的,express 的“res 对象是 Node 自己的响应对象的增强版本,支持所有内置字段和方法。” 这种方法适用于人们已经制作了一个 API 而没有在所有路由中使用 next 的情况。【参考方案5】:

可以在不同的js文件中使用Middle ware函数,也可以使用require函数。以便在 http 请求之前和之后调用它。

    index.js:     
        const logger = require("./logger");    
           const express = require("express");    
           var app = express();    
           app.listen("3000",()=>console.log("listening on 3000..."))    
        app.use(logger("AppServer"));    
        //get expression    
        app.get("/", function(req,res)    
           console.log("res not received");    
            res.send("Hello World");    
           console.log("res received");    
        )   

    logger.js   

    module.exports = (applicationName) =>
        return function log(req,res,next)
       console.log(applicationName+" started "+os.hostname);
        res.on("finish",()=>
            console.log(applicationName+" completed "+os.hostname);
        )
        next();
        ;

output:   
AppServer started hostname-PC   
res not received   
res received   
AppServer completed hostname-PC 

注意:在logger.js中不要使用res.on("finish",callback),可以使用req.on("end",callback)

【讨论】:

以上是关于路由后的 Node Express 4 中间件的主要内容,如果未能解决你的问题,请参考以下文章

Node/Express 的 Passport 身份验证中间件 - 如何保护所有路由

Node.js之Express路由中间件

Node.js---中间件

Node.js 和 Express 排除路由表单 JWT 中间件

Node.js和Express排除路由形式JWT中间件

Node.js_express_中间件 middleware_登录/注册实例