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

我对express和node.js有点陌生,我搞不清楚app.use和app.get之间的区别。看起来你可以同时使用它们来发送信息。例如:

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

似乎和这个是一样的:

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

HTTP方法被设置为GET时调用app.get,而不管HTTP方法如何调用app.use,因此定义了一个位于快速包提供给你访问的所有其他RESTful类型之上的层。

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'));


// ...

通过将/指定为“”路径,app.use()将响应任何以/开头的路径,这些路径都是以/开头的,无论使用的HTTP动词是什么:

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

另一方面,app.get()是Express ` 应用程序路由的一部分,用于在使用GET HTTP谓词请求时匹配和处理特定路由:

  • 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) {
    // ...
    });
    

    vs。

    app.use('/', function (req, res, next) {
    if (req.method !== 'GET' || req.url !== '/')
    return next();
    
    
    // ...
    });
    
  • With multiple handlers for the same route:

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

    vs。

    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);
    
    
    // ...
    });
    });
    
  • With parameters:

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

    vs。

    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;
    // ...
    });
    

Note: Express' implementation of these features are contained in its Router, Layer, and Route.

app.use是来自Connect的“低级”方法,Connect是Express所依赖的中间件框架。

以下是我的指导原则:

  • 如果你想公开一个GET方法,使用app.get
  • 如果你想添加一些中间件(HTTP请求到达你在Express中设置的路由之前的处理程序),或者如果你想让你的路由模块化(例如,从npm模块公开一组路由,其他web应用程序可以使用),可以使用app.use
< p >简单 app.use表示“在所有请求上运行此程序”
app.get的意思是“在一个GET请求上运行这个,对于给定的URL”

app.use &app.get:

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

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

现在,app.use和amp之间有一个混淆;app.all。毫无疑问,它们有一个共同点,那就是它们都可以处理所有类型的HTTP请求。 但是有一些区别,建议我们在中间件中使用app.use,在路由处理中使用app.all
  1. app.use()→只需要一次回调 app.all()→可以接受多个回调

  2. . app.all()→可以接受多个回调
  3. 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. app.use()中的next()调用将调用下一个中间件或任何路由处理程序,但app.all()中的next()调用将只调用下一个路由处理程序(app.all()app.get/post/put...等)。如果后面有任何中间件,它将被跳过。因此,建议将所有中间件始终放在路由处理程序之上。

除了以上的解释,我所经历的:

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

将匹配所有请求开始 '/book'作为URL。所以它也匹配" /book/1 "或" /book/2 "

app.get('/book')

只匹配GET请求与精确匹配。它不会处理像'/book/1'或'/book/2'这样的url

因此,如果你想要一个全局处理程序来处理你所有的路由,那么app.use('/')是选项。app.get('/')将只处理根URL。

到目前为止,我发现有3个主要的区别。第三个不是很明显,你可能会觉得它很有趣。对于表达式router,差异是相同的。这意味着router.use()router.get()或其他postputall等方法也有相同的区别。

1
< / p >
  • app.use(path, callback)将响应任何HTTP请求。
  • app.get(path, callback)将只响应GET HTTP请求。以同样的方式,postput等将响应它们相应的请求。app.all()响应任何HTTP请求,因此在此部分中app.use()app.all()是相同的。

2

  • app.use(path, callback)将匹配请求路径的前缀,并在请求路径的任何前缀与路径参数匹配时响应。例如,如果路径参数是"/",那么它将匹配"/""/about""/users/123"等。
  • app.get(path, callback)这里get将匹配整个路径。其他HTTP请求和app.all()也是如此。例如,如果路径参数是"/",那么它将只匹配"/"

3.

next('route') 工作在app.use()的中间件/回调函数上。它只适用于app.get()app.all()和其他类似功能的其他HTTP请求。

根据表达文档:

next('route')只适用于通过app.METHOD()或router.METHOD()函数加载的中间件函数。

METHOD是中间件函数请求的HTTP方法

.

.

.
从这里开始,我们将使用关键字METHOD而不是getpostall等 但是next('route')是什么?!< / p >

让我们来看看。

next(路线)

我们看到,app.use()app.METHOD()可以接受几个回调/中间件函数。

表达文档:

中间件函数是能够访问请求对象(req)、响应对象(res)以及应用程序请求-响应周期中的下一个中间件函数的函数。下一个中间件函数通常由名为next的变量表示。

如果当前中间件函数没有结束请求-响应周期,它必须调用next()将控制传递给下一个中间件函数。否则,请求将被挂起。

所以我们看到每个中间件函数要么调用下一个中间件函数,要么结束响应。 app.use()app.METHOD()也是如此

但有时在某些情况下,您可能希望跳过当前路由的所有下一个回调函数,但也不想立即结束响应。因为可能还有其他路线需要匹配。因此,要跳过当前路由的所有回调函数而不结束响应,可以运行next('route')。它将跳过当前路由的所有回调函数,并搜索匹配下一个路由。

例如(来自明确的文件):

app.get('/user/:id', function (req, res, next) {
// if the user ID is 0, skip to the next route
if (req.params.id === '0') next('route')
// otherwise pass the control to the next middleware function in this stack
else next()
}, function (req, res, next) {
// send a regular response
res.send('regular')
})


// handler for the /user/:id path, which sends a special response
app.get('/user/:id', function (req, res, next) {
res.send('special')
})

看,在这里,在某种条件下,我们想要跳过下一个回调函数,但也不想结束响应,因为有另一个具有相同路径参数的路由将被匹配,并且该路由将发送一个特殊的响应。(是的,对相同的METHOD多次使用相同的路径参数是有效的。在这种情况下,将匹配所有路由,直到响应结束)。因此,在这种情况下,我们运行next('route'),并跳过当前路由的所有回调函数。在这里,如果条件不满足,则调用下一个回调函数。

这种next('route')行为只能在app.METHOD()函数中实现。

表达文档中调用:

next('route')只适用于通过app.METHOD()或router.METHOD()函数加载的中间件函数。

由于跳过当前路由的所有回调函数在app.use()中是可能的,所以我们在这里应该小心。我们应该只使用app.use()中的中间件函数,在任何情况下都不需要跳过。因为我们要么必须结束响应,要么从头到尾遍历所有回调函数,所以我们根本不能跳过它们。

你可以访问在这里获取更多信息

< p >应用程序。每次请求发送到服务器时,都会调用Use。
唯一的事情是我们应该在处理get, put, post等请求之前调用它

app.use(middleware);
function middleware(req, res, next)
{
console.log("Came in middleware function without arrow");
next();
}

App.get只对给定路径的get请求被调用。

app.get('/myget', myget_function);
function myget_function(req, res)
{
console.log("Came in function myget");
res.send('Hello World! from myget');
}

post只在给定路径的post请求时被调用。

app.post('/mypost', mypost_function);
function mypost_function(req, res)
{
console.log("Came in function mypost");
res.send('Hello World! from mypost');
}