我对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');
});
app.use()
旨在将中间件绑定到您的应用程序。这path
是一个“ mount ”或“ prefix ”路径,并将中间件限制为仅适用于以它开头的任何请求的路径。它甚至可以用来嵌入另一个应用程序:
// 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应用程序路由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) {
// ...
});
对比
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;
// ...
});
注意:Express 对这些功能的实现包含在其
Router
、Layer
和Route
.
app.use
是 Express 所依赖的中间件框架 Connect 的“低级”方法。
这是我的指导方针:
app.get
如果要公开 GET 方法,请使用。app.use
您想添加一些中间件(HTTP 请求到达您在 Express 中设置的路由之前的处理程序),或者如果您想使您的路由模块化(例如,公开一组路由来自其他 Web 应用程序可以使用的 npm 模块)。简单的 app.use 表示“在所有请求上运行”
app.get 表示“在 GET 请求上运行,对于给定的 URL”</p>
app.get
当HTTP 方法设置为时调用GET
,而app.use
不管 HTTP 方法如何调用,因此定义了一个位于 express 包允许您访问的所有其他 RESTful 类型之上的层。
app.use
&之间的区别app.get
:
app.use
→ 一般用于在你的应用程序中引入中间件,可以处理所有类型的 HTTP 请求。
app.get
→ 仅用于处理 GET HTTP 请求。
app.use
现在, &之间存在混淆app.all
。毫无疑问,它们有一个共同点,即两者都可以处理所有类型的 HTTP 请求。但是有一些差异建议我们将 app.use 用于中间件,将 app.all 用于路由处理。
app.use()
→ 只需要一次回调。
app.all()
→ 它可以接受多个回调。
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
next()
call insideapp.use()
将调用下一个中间件或任何路由处理程序,但next()
call insideapp.all()
将仅调用下一个路由处理程序(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 个主要差异。第三个不是那么明显,你可能会觉得它很有趣。express 的区别是一样的router
。这意味着router.use()
androuter.get()
或 other post
, put
, all
, etc 方法也有相同的区别。
1
app.use(path, callback)
将响应任何 HTTP 请求。app.get(path, callback)
只会响应GET
HTTP 请求。同理,post
,put
等会响应其相应的请求。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()
. 它仅适用于其他 HTTP 请求app.get()
和app.all()
其他类似功能。
根据快递文件:
next('route') 仅适用于使用 app.METHOD() 或 router.METHOD() 函数加载的中间件函数。
METHOD 是中间件函数处理的请求的 HTTP 方法(例如 GET、PUT 或 POST),小写。
从这里我们将使用关键字 METHOD 代替get
, post
,all
等。
但是什么是next('route')
?!
让我们来看看。
我们看到,app.use()
或者app.METHOD()
可以采取几个回调/中间件函数。
从快递文档中:
中间件函数是可以访问请求对象 (req)、响应对象 (res) 和应用程序请求-响应周期中的下一个中间件函数的函数。next 中间件函数通常由名为 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')
})
看,在某种情况下(req.params.id === '0')
,我们想跳过下一个回调函数,但又不想结束响应,因为有另一条具有相同路径参数的路由将被匹配,并且该路由将发送一个特殊的响应。METHOD
(是的,多次使用相同的路径参数是有效的。在这种情况下,所有路由都将匹配到响应结束)。所以在这种情况下,我们运行next('route')
并且跳过当前路由的所有回调函数。这里如果条件不满足,那么我们调用下一个回调函数。
这种next('route')
行为仅在app.METHOD()
函数中是可能的。
从快速文档中回顾:
next('route') 仅适用于使用 app.METHOD() 或 router.METHOD() 函数加载的中间件函数。
由于跳过当前路由的所有回调函数在 中是不可能的app.use()
,所以在这里我们应该小心。app.use()
我们应该只使用在任何情况下都不需要跳过的中间件函数。因为我们要么必须结束响应,要么从头到尾遍历所有的回调函数,我们根本不能跳过它们。
您可以访问这里了解更多信息