node.js Express next 函数,到底是干什么用的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13133071/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Express next function, what is it really for?
提问by Andreas Selenwall
Have been trying to find a good description of what the next()method does. In the Express documentation it says that next('route')can be used to jump to that route and skip all routes in between, but sometimes nextis called without arguments. Anybody knows of a good tutorial etc that describes the nextfunction?
一直试图找到一个关于该next()方法的作用的很好的描述。在 Express 文档中,它说next('route')可用于跳转到该路由并跳过其间的所有路由,但有时next不带参数调用。有人知道描述该next功能的好教程等吗?
回答by Alex Wayne
next()with no arguments says "just kidding, I don't actual want to handle this". It goes back in and tries to find the next route that would match.
next()没有论据说“开个玩笑,我真的不想处理这个”。它返回并尝试找到下一条匹配的路线。
This is useful, say if you want to have some kind of page manager with url slugs, as well as lots of other things, but here's an example.
这很有用,比如说,如果您想要某种带有 url slug 的页面管理器以及许多其他东西,但这里有一个示例。
app.get('/:pageslug', function(req, res, next){
var page = db.findPage(req.params.pageslug);
if (page) {
res.send(page.body);
} else {
next();
}
});
app.get('/other_routes', function() {
//...
});
That made up code should check a database for a page with a certain id slug. If it finds one render it! if it doesn't find one then ignore this route handler and check for other ones.
该组成的代码应该检查数据库中是否存在具有特定 id slug 的页面。如果它找到一个渲染它!如果没有找到,则忽略此路由处理程序并检查其他路由处理程序。
So next()with no arguments allows to pretend you didn't handle the route so that something else can pick it up instead.
所以next()没有参数允许假装你没有处理路线,以便其他东西可以代替它。
Or a hit counter with app.all('*'). Which allows you to execute some shared setup code and then move on to other routes to do something more specific.
或带有 的计数器app.all('*')。这允许您执行一些共享的设置代码,然后继续执行其他路由以执行更具体的操作。
app.all('*', function(req, res, next){
myHitCounter.count += 1;
next();
});
app.get('/other_routes', function() {
//...
});
回答by Pickels
In most frameworks you get a request and you want to return a response. Because of the async nature of Node.js you run into problems with nested call backs if you are doing non trivial stuff. To keep this from happening Connect.js (prior to v4.0, Express.js was a layer on top of connect.js) has something that is called middleware which is a function with 2, 3 or 4 parameters.
在大多数框架中,您会收到一个请求并希望返回一个响应。由于 Node.js 的异步特性,如果您正在做一些重要的事情,您会遇到嵌套回调的问题。为了防止这种情况发生,Connect.js(在 v4.0 之前,Express.js 是位于 connect.js 之上的一层)有一个叫做中间件的东西,它是一个带有 2、3 或 4 个参数的函数。
function (<err>, req, res, next) {}
Your Express.js app is a stack of these functions.
您的 Express.js 应用程序是这些函数的堆栈。


The router is special, it's middleware that lets you execute one or more middleware for a certain url. So it's a stack inside a stack.
路由器很特别,它是一个中间件,可以让您为某个 url 执行一个或多个中间件。所以它是一个堆栈中的堆栈。
So what does next do? Simple, it tells your app to run the next middleware. But what happens when you pass something to next? Express will abort the current stack and will run all the middleware that has 4 parameters.
那么接下来做什么呢?很简单,它告诉您的应用程序运行下一个中间件。但是当你将一些东西传递给 next 时会发生什么?Express 将中止当前堆栈并运行所有具有 4 个参数的中间件。
function (err, req, res, next) {}
This middleware is used to process any errors. I like to do the following:
该中间件用于处理任何错误。我喜欢做以下事情:
next({ type: 'database', error: 'datacenter blew up' });
With this error I would probably tell the user something went wrong and log the real error.
有了这个错误,我可能会告诉用户出了什么问题并记录真正的错误。
function (err, req, res, next) {
if (err.type === 'database') {
res.send('Something went wrong user');
console.log(err.error);
}
};
If you picture your Express.js application as a stack you probably will be able to fix a lot of weirdness yourself. For example when you add your Cookie middleware after you router it makes sense that your routes wont have cookies.
如果你把你的 Express.js 应用程序想象成一个堆栈,你可能会自己解决很多奇怪的问题。例如,当您在路由器之后添加 Cookie 中间件时,您的路由不会有 cookie 是有意义的。
回答by d512
IMHO, the accepted answer to this question is not really accurate. As others have stated, it's really about controlling when next handler in the chain is run. But I wanted to provide a little more code to make it more concrete. Say you have this simple express app:
恕我直言,这个问题的公认答案并不准确。正如其他人所说,这实际上是关于控制链中的下一个处理程序何时运行。但我想提供更多代码以使其更具体。假设你有这个简单的 express 应用:
var express = require('express');
var app = express();
app.get('/user/:id', function (req, res, next) {
console.log('before request handler');
next();
});
app.get('/user/:id', function (req, res, next) {
console.log('handling request');
res.sendStatus(200);
next();
});
app.get('/user/:id', function (req, res, next) {
console.log('after request handler');
next();
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});
If you do
如果你这样做
curl http://localhost:3000/user/123
you will see this printed to console:
你会看到这个打印到控制台:
before request handler
handling request
after request handler
Now if you comment out the call to next()in the middle handler like this:
现在,如果您next()像这样注释掉对中间处理程序的调用:
app.get('/user/:id', function (req, res, next) {
console.log('handling request');
res.sendStatus(200);
//next();
});
You will see this on the console:
您将在控制台上看到:
before request handler
handling request
Notice that the last handler (the one that prints after request handler) does not run. That's because you are no longer telling express to run the next handler.
请注意,最后一个处理程序(打印 的处理程序after request handler)没有运行。那是因为您不再告诉 express 运行下一个处理程序。
So it doesn't really matter if your "main" handler (the one that returns 200) was successful or not, if you want the rest of the middlewares to run, you have to call next().
因此,您的“主要”处理程序(返回 200 的处理程序)是否成功并不重要,如果您希望其余的中间件运行,则必须调用next().
When would this come in handy? Let's say you want to log all requests that came in to some database regardless of whether or not the request succeeded.
这什么时候会派上用场?假设您想记录进入某个数据库的所有请求,而不管请求是否成功。
app.get('/user/:id', function (req, res, next) {
try {
// ...
}
catch (ex) {
// ...
}
finally {
// go to the next handler regardless of what happened in this one
next();
}
});
app.get('/user/:id', function (req, res, next) {
logToDatabase(req);
next();
});
If you want the second handler to run, you have to call next()in the first handler.
如果要运行第二个处理程序,则必须调用next()第一个处理程序。
Remember that node is async so it can't know when the first handler's callback has finished. You have to tell it by calling next().
请记住,节点是异步的,因此它无法知道第一个处理程序的回调何时完成。你必须通过调用告诉它next()。
回答by kyasar
next() without parameter invokes the next route handler OR next middleware in framework.
next() 不带参数调用框架中的下一个路由处理程序或下一个中间件。
回答by Gammer
Its simply means pass control to the next handler.
它只是意味着将控制权传递给下一个处理程序。
Cheers
干杯
回答by Hukmaram
Notice the call above to next(). Calling this function invokes the next middleware function in the app. The next() function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. The next() function could be named anything, but by convention, it is always named “next”. To avoid confusion, always use this convention.
注意上面对 next() 的调用。调用此函数会调用应用程序中的下一个中间件函数。next() 函数不是 Node.js 或 Express API 的一部分,而是传递给中间件函数的第三个参数。next() 函数可以命名为任何名称,但按照惯例,它始终命名为“next”。为避免混淆,请始终使用此约定。
回答by Ula
Question also asked about use of next('route') which seems to be covered week in provided answers so far:
问题还询问了 next('route') 的使用,到目前为止提供的答案似乎涵盖了一周:
- USAGE OF next():
- next() 的用法:
In short: next middleware function.
简而言之:下一个中间件功能。
Extract from this official Express JS documentation - 'writing-middleware' page:
摘自这个官方Express JS 文档 - 'writing-middleware' 页面:
"The middleware function myLogger simply prints a message, then passes on the request to the next middleware functionin the stack by calling the next() function."
“中间件函数 myLogger 只是打印一条消息,然后通过调用 next() 函数将请求传递给堆栈中的下一个中间件函数。”
var express = require('express')
var app = express()
var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
app.use(myLogger)
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(3000)
This page of Express JS documentationstates "If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging."
Express JS 文档的这个页面声明“如果当前中间件函数没有结束请求-响应循环,它必须调用 next() 将控制权传递给下一个中间件函数。否则,请求将被挂起。”
- USAGE OF next('route') :
- next('route') 的用法:
In short: next route(vs. next middleware functionin case of next() )
简而言之:下一条路线(与next() 情况下的下一个中间件功能)
Extract from this Express JS documentation - 'using-middleware' page:
摘自此Express JS 文档 - 'using-middleware' 页面:
"To skip the rest of the middleware functions from a router middleware stack, call next('route') to pass control to the next route. NOTE: next('route') will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.
“要跳过路由器中间件堆栈中的其余中间件功能,请调用 next('route') 将控制权传递给下一个 route。注意:next('route') 将仅在使用app.METHOD() 或 router.METHOD() 函数。
This example shows a middleware sub-stack that handles GET requests to the /user/:id path."
此示例显示了一个中间件子堆栈,用于处理对 /user/:id 路径的 GET 请求。”
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) {
// render a regular page
res.render('regular')
})
// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {
res.render('special')
})

