Nodejs express4.x的app.use与router.use的优先级

Nodejs express4.x的app.use与router.use的优先级

express4.x,将express的自带中间件都独立出来了。独立出来的一个模块还有router。 想请问下。这之后,app.use与router.use这两个方法注册的中间件执行时有优先级吗。

5 回复

Nodejs express4.x的app.use与router.use的优先级

在Express 4.x版本中,app.userouter.use 方法用于注册中间件。虽然它们的功能相似,但在实际应用中可能会遇到一些细微的差别。本文将探讨这两个方法在中间件执行顺序上的差异。

app.use vs router.use

  1. app.use

    • app.use 是全局中间件,应用于整个应用程序。它可以处理所有路由请求。
    • 它通常用于设置全局中间件,如错误处理、日志记录等。
  2. router.use

    • router.use 是局部中间件,仅应用于特定的路由或一组路由。
    • 它可以用于对特定路由进行预处理或后处理。

执行顺序

在Express应用中,中间件的执行顺序非常重要。app.userouter.use 注册的中间件会根据它们被添加到应用中的顺序来执行。具体来说:

  • 如果你在一个路由之前使用 app.use 添加了一个中间件,那么这个中间件会在所有匹配该路由的请求之前执行。
  • 同样地,如果在某个路由处理器之前使用 router.use 添加了一个中间件,那么这个中间件会在所有匹配该路由的请求之前执行。

示例代码

const express = require('express');
const app = express();
const router = express.Router();

// 全局中间件
app.use((req, res, next) => {
    console.log('Global middleware: Before route');
    next();
});

// 路由中间件
router.use((req, res, next) => {
    console.log('Route middleware: Before route handler');
    next();
});

// 路由处理器
router.get('/', (req, res) => {
    res.send('Hello World!');
});

// 将路由挂载到应用
app.use('/api', router);

// 错误处理中间件
app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('Something broke!');
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

在这个例子中:

  1. 当访问 /api/ 时,首先会触发全局中间件 app.use
  2. 然后会触发路由中间件 router.use
  3. 最后,路由处理器 router.get 会被调用。
  4. 如果在处理过程中发生错误,错误处理中间件 app.use 会被触发。

总结来说,app.userouter.use 的执行顺序取决于它们被添加到应用中的位置。全局中间件通常先于局部中间件执行,但具体的顺序取决于它们在代码中的排列顺序。


补充下说明。执行时的优先级指的是。.use方法在express3.x及之前是先注册,先响应。 然后现在有两个对象下的.use方法(app.use和router.use),他们注册的中间件执行时天生就有优先级别吗。(举个 极端的例子就是是先响应完app.use再响应router.use。还是仍然一视同仁,先注册,先响应?)

看源码就知道了,app.use调用的是Router的实例_router.use,即Router的原型方法,跟router.use一样

 this._router = new Router({
      caseSensitive: this.enabled('case sensitive routing'),
      strict: this.enabled('strict routing')
    });
var proto = module.exports = function(options) {
  options = options || {};

function router(req, res, next) { router.handle(req, res, next); }

// mixin Router class functions router.proto = proto;

router.params = {}; router._params = []; router.caseSensitive = options.caseSensitive; router.strict = options.strict; router.stack = [];

return router; };

但是看调用每次调用组件’var router = express.Router([options]);‘都是返回一个新的function,有自己的stack。 最后,看了一下文档… router.use需要调用app.use(’/foo’, router);才会生效啊!所以没有优先级的关系。

最后一句正解啊!没有认真重新看文档。当时想着问题的时候也懒得去找源码看,惭愧= =。佩服你思考的方式。从源码出发,然后发现

但是看调用每次调用组件'var router = express.Router([options]);'都是返回一个新的function,有自己的stack。

这个问题,再翻阅文档,最后得到答案。 要向你学习这种思考的方式,感谢。

在Express 4.x中,app.userouter.use 注册的中间件没有严格的优先级关系。它们的执行顺序取决于它们被注册的先后顺序。

具体来说:

  1. app.use 是应用级别的中间件,它作用于整个应用程序,适用于所有路由。
  2. router.use 是路由级别的中间件,它仅作用于特定的路由路径。

当你在一个应用中同时使用 app.userouter.use 时,它们的执行顺序依赖于它们被注册的顺序。通常情况下,先注册的中间件会先执行。

示例代码

const express = require('express');
const app = express();
const router = express.Router();

// 应用级别的中间件
app.use((req, res, next) => {
    console.log('App-level middleware executed');
    next();
});

// 路由级别的中间件
router.use((req, res, next) => {
    console.log('Router-level middleware executed');
    next();
});

// 定义一个路由,使用这个路由中间件
router.get('/', (req, res) => {
    res.send('Hello World!');
});

// 将路由挂载到应用
app.use('/path', router);

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

执行顺序

假设你访问 /path/,输出将会是:

App-level middleware executed
Router-level middleware executed

这是因为 app.use 先于 router.use 被注册。如果 router.use 先于 app.use 注册,那么输出顺序将会相反。

总结

  • app.userouter.use 没有内在的优先级。
  • 它们的执行顺序取决于它们被注册的先后顺序。
  • app.use 对应应用级别,而 router.use 对应路由级别。

通过理解这些基本概念,你可以更好地管理和组织你的中间件逻辑。

回到顶部