Nodejs中app.use(app.router);究竟是什么意思

Nodejs中app.use(app.router);究竟是什么意思

网上这一些答案看的不是很懂

今天在用express-flash的时候

app.use(express.cookieParser('shopmall'));
app.use(express.session({ cookie: { maxAge: 60000 }}));
app.use(flash());

必须要放在app.use(app.router);的前面,不然的话会报错说没有req.flash这个方法


4 回复

Node.js 中 app.use(app.router); 究竟是什么意思?

引言

在使用 Express 框架时,你可能会遇到类似以下的代码片段:

app.use(express.cookieParser('shopmall'));
app.use(express.session({ cookie: { maxAge: 60000 }}));
app.use(flash());

这些中间件必须放在 app.use(app.router); 的前面。那么,app.use(app.router); 到底是什么意思呢?本文将通过一些简单的解释和示例代码来解答这个问题。

解释

在早期版本的 Express(如 v2.x)中,app.use(app.router); 是一个重要的步骤,用于注册路由处理程序。简单来说,app.use(app.router); 告诉 Express 在所有静态文件中间件之后运行路由中间件。然而,在现代版本的 Express(如 v4.x 及以上),app.use(app.router); 已经被废弃了。Express 自动处理路由,无需显式调用 app.use(app.router);

示例代码

让我们看看一个简单的 Express 应用程序,它使用了一些常见的中间件:

const express = require('express');
const app = express();

// 使用 Cookie 解析器
app.use(express.cookieParser('shopmall'));

// 使用 Session 中间件
app.use(express.session({ cookie: { maxAge: 60000 }}));

// 使用 Flash 中间件
app.use(flash());

// 定义一个路由
app.get('/', (req, res) => {
    req.flash('info', 'Hello, world!');
    res.send('Hello, world!');
});

// 启动服务器
app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

在这个例子中,我们不需要显式地调用 app.use(app.router);,因为现代 Express 版本会自动处理路由。

为什么需要放在前面?

对于你的问题,关于为什么 app.use(express.session({ cookie: { maxAge: 60000 }}));app.use(flash()); 必须放在 app.use(app.router); 前面,这实际上是因为在旧版本的 Express 中,app.router 会在所有中间件之后运行。因此,如果把它们放在 app.use(app.router); 后面,可能会影响中间件的功能。而在现代版本中,由于 app.use(app.router); 已经被废弃,这个问题就不再存在了。

结论

总之,app.use(app.router); 在现代 Express 应用中已经不再必要,理解这一点可以帮助你更好地编写和维护你的 Express 应用。


app.router的用途这里讲的很详细了。

简单理解:里边会创建一个路由map,把类似app.get、app.post等的所有路由的url和callback做一个映射保存,当req.url命中路由时执行相应的回调。如果不显式调用app.use(app.router);则会在第一条路由里边隐式调用。

这里边,调用app.use(app.router);时会暂存req对象,当后面再定义路由时, app.get('/foo', function(req, res, next) {});这里的req应该用的是之前保存下来的,所以会出现没有req.flash的错误(没细看express源码,这是猜测的~)。

express 的中间件写法.

完整而言是

app.use(function (req, res, next){
   //为了我们能够使用 req.flash

req.flash = req.flash || {}; next(); });

然后,接下来我就可以获取req.flash 的定义了…为什么要放在前面?? 因为程序是自上而下的运行啊…

app.use(app.router); 在较旧版本的 Express(例如 3.x 版本)中用于定义路由处理中间件的位置。这行代码告诉 Express 在所有中间件之后注册路由处理程序。

但在现代的 Express 版本(4.x 及以上)中,这行代码已经不再需要了。路由和中间件会自动被应用到所有请求上,无需显式调用 app.router

根据你的问题,app.use(app.router); 需要在 app.use(flash()) 前面的原因是因为在较旧版本的 Express 中,中间件必须在路由之前被注册。flash() 中间件依赖于请求/响应对象上的某些属性,这些属性通常由其他中间件(如 cookieParsersession)设置。

示例代码

假设你使用的是较旧版本的 Express(例如 3.x),可以这样写:

var express = require('express');
var app = express();

// 使用中间件
app.use(express.cookieParser('shopmall'));
app.use(express.session({ cookie: { maxAge: 60000 }}));
app.use(app.router); // 注意:这是在Express 3.x中的用法

// 定义路由
app.get('/', function(req, res) {
    req.flash('info', 'Hello World!');
    res.send('Hello World!');
});

// 启动服务器
app.listen(3000);

现代版本的替代方式

如果你使用的是现代版本的 Express(例如 4.x 或更高版本),你可以直接这样写:

var express = require('express');
var session = require('express-session');
var flash = require('connect-flash');
var app = express();

// 使用中间件
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.use(session({ cookie: { maxAge: 60000 } }));
app.use(flash());

// 定义路由
app.get('/', function(req, res) {
    req.flash('info', 'Hello World!');
    res.send('Hello World!');
});

// 启动服务器
app.listen(3000);

在这段代码中,我们不需要显式调用 app.router,因为 Express 会自动处理所有中间件和路由。

回到顶部