express.js中app.use和app.get之间的区别


220

我是表示和node.js的新手,我无法弄清app.use和app.get之间的区别。似乎您可以同时使用它们来发送信息。例如:

app.use('/',function(req, res,next) {
    res.send('Hello');
    next();
});

似乎与此相同:

app.get('/', function (req,res) {
   res.send('Hello');
});

1
像你看上去有三个不同的答案,这些都有助于东西话题:)这里有一个相关的问题stackoverflow.com/questions/11321635/...
本杰明Gruenbaum

是的,所有好的答案。谢谢,我来看一下。
Andre Vorobyov

Answers:


219

app.use()用于将中间件绑定到您的应用程序。它path是一个“ 安装 ”或“ 前缀 ”路径,并将中间件限制为仅适用于以它开头的任何请求的路径。它甚至可以用于嵌入另一个应用程序:

// subapp.js
var express = require('express');
var app = modules.exports = express();
// ...
// server.js
var express = require('express');
var app = express();

app.use('/subapp', require('./subapp'));

// ...

通过指定/为“ mount ”路径,app.use()将响应以开头的所有路径,/并且所有路径均与使用的HTTP动词无关:

  • GET /
  • PUT /foo
  • POST /foo/bar
  • 等等

app.get()另一方面,它是Express 应用程序路由的一部分,旨在与GETHTTP动词一起请求时匹配和处理特定路由:

  • GET /

而且,您的示例的等效路由app.use()实际上是:

app.all(/^\/.*/, function (req, res) {
    res.send('Hello');
});

更新:试图更好地证明差异。

包括在内的路由方法app.get()是方便使用的方法,可帮助您更准确地将响应与请求对齐。它们还增加了对功能的支持,例如参数next('route')

每个app.get()调用中都有一个app.use(),因此您当然可以app.use()直接使用来完成所有这些操作。但是,这样做通常需要(可能不必要)重新实现各种数量的样板代码。

例子:

  • 对于简单的静态路由:

    app.get('/', function (req, res) {
      // ...
    });

    app.use('/', function (req, res, next) {
      if (req.method !== 'GET' || req.url !== '/')
        return next();
    
      // ...
    });
  • 对于同一条路线有多个处理程序:

    app.get('/', authorize('ADMIN'), function (req, res) {
      // ...
    });

    const authorizeAdmin = authorize('ADMIN');
    
    app.use('/', function (req, res, next) {
      if (req.method !== 'GET' || req.url !== '/')
        return next();
    
      authorizeAdmin(req, res, function (err) {
        if (err) return next(err);
    
        // ...
      });
    });
  • 带有参数:

    app.get('/item/:id', function (req, res) {
      let id = req.params.id;
      // ...
    });

    const pathToRegExp = require('path-to-regexp');
    
    function prepareParams(matches, pathKeys, previousParams) {
      var params = previousParams || {};
    
      // TODO: support repeating keys...
      matches.slice(1).forEach(function (segment, index) {
        let { name } = pathKeys[index];
        params[name] = segment;
      });
    
      return params;
    }
    
    const itemIdKeys = [];
    const itemIdPattern = pathToRegExp('/item/:id', itemIdKeys);
    
    app.use('/', function (req, res, next) {
      if (req.method !== 'GET') return next();
    
      var urlMatch = itemIdPattern.exec(req.url);
      if (!urlMatch) return next();
    
      if (itemIdKeys && itemIdKeys.length)
        req.params = prepareParams(urlMatch, itemIdKeys, req.params);
    
      let id = req.params.id;
      // ...
    });

注:快车实现这些功能都包含在它的RouterLayerRoute


3
提及嵌入式应用程序的荣誉。这是组织快速中间件的一种非常方便的方法。
wprl

4
公平地说,app.use可以完成app.get,app.post,app.put中的每一项工作,但反之亦然吗?
ngungo 2014年

6
仍然很难理解。
Jeb50

1
知道有什么用和得到是很好,但是没有人能很好地解释它们的不同功能。据我所知,所有.use处理函数都首先运行,.use匹配以指定路径开头的任何路径(即.use('/',...)和.get('/ *',... )将匹配相同的路径)。对我来说,当我看到运动部件时,更容易理解整体概念。
snarf '18

2
我认为值得一提的是,此响应已过时且过时,从我发表评论之日起您不需要path-to-regexp或不再需要任何其他内容,您可以在该use方法的第一个参数中直接使用route参数。
vdegenne

50

app.use 是Express依赖的中间件框架Connect的“较低级别”方法。

这是我的指导方针:

  • 使用app.get是否要公开一个GET方法。
  • 使用app.use,如果你想添加一些中间件(的处理程序HTTP请求它到达您在快速设置路线之前),或者如果你想使你的路由模块(例如,公开了一组路线来自其他Web应用程序可以使用的npm模块)。

但是,如果我不在乎该方法,我可以app.use用来处理一些路线吗?否则我们绝不应该使用app.use路由。
Elemento0

您可以使用app.use将路线移动到单独的文件eq。users.js,buildings.js
罗伯·安吉利尔

1
尽管上面的一个答案收集了更多的UP / AGREE,但是您的答案将包括中间件在内的复杂事物转换为一些简单的单词kudo。
Jeb50


28

app.getHTTP方法设置GET为时app.use调用,而无论HTTP方法如何都调用,因此它定义了一个层,该层位于Express包允许您访问的所有其他RESTful类型的顶部。


19

app.use&之间的区别app.get

app.use →它通常用于在您的应用程序中引入中间件,并且可以处理所有类型的HTTP请求。

app.get →仅用于处理GET HTTP请求。

现在,app.use&之间存在混淆app.all。毫无疑问,它们中有一个共同点,即两者都可以处理各种HTTP请求。但是存在一些差异,建议我们将app.use用于中间件,将app.all用于路由处理。

  1. app.use()→仅需要一个回调。
    app.all()→它可能需要多个回调。

  2. app.use()将仅查看url是否以指定的路径开头。
    但是,app.all()将匹配完整路径。

例如,

app.use( "/book" , middleware);
// will match /book
// will match /book/author
// will match /book/subject

app.all( "/book" , handler);
// will match /book
// won't match /book/author   
// won't match /book/subject    

app.all( "/book/*" , handler);
// won't match /book        
// will match /book/author
// will match /book/subject
  1. next()在内部调用app.use()将调用下一个中间件或任何路由处理程序,但next()在内部app.all()调用将仅调用下一个路由处理程序(app.all()app.get/post/put...等等)。如果之后有任何中间件,则将被跳过。因此,建议将所有中间件始终置于路由处理程序之上。

1
您的观点3似乎不适用于Express 4.16。实际上next()app.all('/*', ...)在内部调用将在app.use('/', ...)文件中执行更高版本。也许我在那儿误会了你。否则很有帮助的解释。
BeetleJuice

在4.17中,我观察到与@BeetleJuice相同
David Lopez

4

除了上述说明,我的经验是:

app.use('/book', handler);  

将匹配所有 “ / book” 开头的请求作为URL。因此它也匹配'/ book / 1'或'/ book / 2'

app.get('/book')  

匹配完全匹配的 GET请求。它不会处理“ / book / 1”或“ / book / 2”之类的URL

因此,如果您希望使用一个全局处理程序来处理所有路由,则app.use('/')可以选择。app.get('/')将仅处理根URL。

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.