app.all('*')和app.use('/')之间的区别


Answers:


119

在大多数情况下,它们将等效地工作。最大的不同是中间件的应用顺序:

  • app.all() 附加到应用程序的路由器,因此只要到达app.router中间件即可使用(它处理所有方法路由... GET,POST等)。

注意:app.router已在Express 4.x中弃用

  • app.use()附加到应用程序的主要中间件堆栈,因此按中间件指定的顺序使用。例如,如果您把它放在第一位,它将是第一件事。如果将它放在最后(在路由器之后),则通常根本不会运行它。

通常,如果要对所有路由进行全局处理,则app.use()是更好的选择。而且,它的未来错误发生的可能性较小,因为express 0.4可能会删除隐式路由器(这意味着路由器在中间件中的位置将比现在更重要,因为从技术上讲,您甚至不必使用它马上)。


15
Express 4.x之后仍然适用吗?app.router已删除。
ruffrey

1
您可以使用next("route")app.all,但不与app.use
JozefMikušinec17年

@JozefMikusinec文档似乎建议其他方式…… expressjs.com
en/guide/

您的链接没有提及next('route'),但是我看了看API,您是对的。
JozefMikušinec17年

2
我进一步研究了@ musicin3d,发现了此GitHub问题,该问题确认“ next()和next('route')与app.use没什么区别”(引用)。他们应该更改文档。
JozefMikušinec17年

87

app.use只接受一个回调函数,它用于中间件。中间件通常不处理请求和响应(从技术上讲,它们可以),它们只是处理输入数据,并将其移交给队列中的下一个处理程序。

app.use([path], function)

app.all需要多个回调,并用于路由。通过多个回调,您可以过滤请求并发送响应。它在express.js的过滤器中进行了解释

app.all(path, [callback...], callback)

app.use仅查看url是否以指定路径开头

app.use( "/product" , mymiddleware);
// will match /product
// will match /product/cool
// will match /product/foo

app.all将匹配完整路径

app.all( "/product" , handler);
// will match /product
// won't match /product/cool   <-- important
// won't match /product/foo    <-- important

app.all( "/product/*" , handler);
// won't match /product        <-- Important
// will match /product/
// will match /product/cool
// will match /product/foo

17
至少在v4中,app.use具有一个或多个中间件功能,而不是“仅一个”功能。
杰斯·奥斯汀

2
app.use仅查看url是否以指定的路径开头; app.all将匹配完整的路径。这是主要区别。
meizilp

@frogcjn不,它不应该忽略它在我的问题中的*和/。
ostergaard

15
  • 应用用途:

    1. 将中间件软件注入到您的前端控制器中,进行配置,例如:标头,Cookie,会话等。
    2. 必须在app [http_method]之前编写,否则将不会执行。
    3. 多个呼叫按写入顺序处理
  • 惊恐:

    1. (例如app [http_method])用于配置路由的控制器
    2. “全部”表示它适用于所有http方法。
    3. 多个呼叫按写入顺序处理

看一下这个expressJs代码示例:

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

app.use(function frontControllerMiddlewareExecuted(req, res, next){
  console.log('(1) this frontControllerMiddlewareExecuted is executed');
  next();
});

app.all('*', function(req, res, next){
  console.log('(2) route middleware for all method and path pattern "*", executed first and can do stuff before going next');
  next();
});

app.all('/hello', function(req, res, next){
  console.log('(3) route middleware for all method and path pattern "/hello", executed second and can do stuff before going next');
  next();
});

app.use(function frontControllerMiddlewareNotExecuted(req, res, next){
  console.log('(4) this frontControllerMiddlewareNotExecuted is not executed');
  next();
});

app.get('/hello', function(req, res){
  console.log('(5) route middleware for method GET and path patter "/hello", executed last and I do my stuff sending response');
  res.send('Hello World');
});

app.listen(80);

这是访问路由“ / hello”时的日志:

(1) this frontControllerMiddlewareExecuted is executed
(2) route middleware for all method and path pattern "*", executed first and can do stuff before going next
(3) route middleware for all method and path pattern "/hello", executed second and can do stuff before going next
(5) route middleware for method GET and path patter "/hello", executed last and I do my stuff sending response

6
在express 4.x上逐字运行此示例后,实际上按顺序运行全部5个。这很可能是由于自撰写本文档以来的近三年中表达的变化,但我只是想为清楚起见添加此内容。
内森威伯

11

使用app.use(),“挂载”路径被剥离,并且对中间件功能不可见:

app.use('/static', express.static(__dirname + '/public'));

express.static除非已装载的中间件function()req.url包含此前缀(/static),否则不会调用已安装的中间件function(),此时调用该函数时会删除该前缀。

使用app.all(),则没有该行为。


该问题仅询问有关app.use('/',...)的问题。
ostergaard 2013年

这是对这个问题的正确答案,在2018年仍然如此!中间件也可以通过all()进行安装...唯一的区别是执行中间件时,安装路径已被剥离。
Xatian

4

是的,app.all()当使用任何类型的请求方法(POST,GET,PUT或DELETE)请求特定URI时都会被调用

另一方面,app.use()它可用于您可能拥有的任何中间件,并将其安装在路径前缀上,并且在请求该路由下的URI时都会被调用。

这是app.allapp.use的文档。


谢谢,但我认为您错过了app.all通配符和app.use根路径,这使它们几乎完全相同,不是吗?除了app.all可以接受一系列回调,而app.use只能接受一个回调-对吗?
ostergaard 2013年

1

以上答案有两个不同之处。

第一个:app.all接受正则表达式作为其路径参数。app.use不接受正则表达式。

第二个: app.all(path,handler)app[method](path,handler),处理者path必须与所有人 相同path。至此,“ app [方法]”路径已完成。

app.use(path,hanlder),如果use的路径是完整的,则处理程序的路径必须为'/'。如果use的路径是完整路径的开始,则处理程序路径必须为完整路径的其余部分。

 app.use('/users', users);

  //users.js:  the handler will be called when matchs `/user/` path
      router.get('/', function(req, res, next) {
      res.send('respond with a resource');
    });
  // others.js: the handler will be called when matchs `/users/users` path
      router.get('/users', function(req, res, next) {
      res.send('respond with a resource');
    });

app.all('/users', users);

//others.js: the handler wil be called when matchs `/`path
router.get('/', function(req, res, next) {
     res.send('respond with a resource');
});
//users.js: the handler will be called when matchs `/users` path
router.get('/users', function(req, res, next) {
    res.send('respond with a resource');
 });

0

主要区别有两个:

1.模式匹配(由Palani给出的答案)
2. next(route)在使用加载的中间件的函数体内不起作用app.use。在文档的链接中对此进行了说明:

NOTE: next('route') will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.

链接:http//expressjs.com/en/guide/using-middleware.html

next('route')从以下示例可以看出的工作效果:

app.get('/',
(req,res,next)=>{console.log("1");
next(route); //The code here skips ALL the following middlewares
}
(req,res,next)=>{next();}, //skipped
(req,res,next)=>{next();}  //skipped
);

//Not skipped
app.get('/',function(req,res,next){console.log("2");next();});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.