何时在 Node.js 中使用 next() 并返回 next()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16810449/
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
When to use next() and return next() in Node.js
提问by Amol M Kulkarni
Scenario: Consider the following is the part of code from a node web app.
场景:考虑以下是来自节点 Web 应用程序的代码部分。
app.get('/users/:id?', function(req, res, next){
var id = req.params.id;
if (id) {
// do something
} else {
next(); //or return next();
}
});
Issue: I am checking which one to go with just next()or return next(). Above sample code works exactly the same for both & did not show any difference in execution.
问题:我正在检查只使用next()或return next()。上面的示例代码对两者的工作方式完全相同,并且在执行上没有显示任何差异。
Question: Can some one put light on this, when to use next()and when to use return next()and some important difference?
问题:有人可以阐明这一点,何时使用next()以及何时使用return next()以及一些重要的区别吗?
回答by PJCHENder
As @Laurent Perrin's answer:
正如@Laurent Perrin 的回答:
If you don't do it, you risk triggering the callback a second time later, which usually has devastating results
如果你不这样做,你就有可能在之后第二次触发回调,这通常会带来毁灭性的结果
I give an example here if you write middleware like this:
如果你写这样的中间件,我在这里举个例子:
app.use((req, res, next) => {
console.log('This is a middleware')
next()
console.log('This is first-half middleware')
})
app.use((req, res, next) => {
console.log('This is second middleware')
next()
})
app.use((req, res, next) => {
console.log('This is third middleware')
next()
})
You will find out that the output in console is:
你会发现控制台的输出是:
This is a middleware
This is second middleware
This is third middleware
This is first-half middleware
That is, it runs the code below next() after all middleware function finished.
也就是说,它在所有中间件功能完成后运行 next() 下面的代码。
However, if you use return next(), it will jump out the callback immediately and the code below return next()in the callback will be unreachable.
但是,如果使用return next(),它会立即跳出回调,并且回调中下面的代码return next()将无法访问。
回答by Laurent Perrin
Some people always write return next()is to ensure that the execution stops after triggering the callback.
有些人总是写return next()是为了保证在触发回调后停止执行。
If you don't do it, you risk triggering the callback a second time later, which usually has devastating results. Your code is fine as it is, but I would rewrite it as:
如果你不这样做,你就有可能在之后第二次触发回调,这通常会带来毁灭性的结果。您的代码很好,但我会将其重写为:
app.get('/users/:id?', function(req, res, next){
var id = req.params.id;
if(!id)
return next();
// do something
});
It saves me an indentation level, and when I read the code again later, I'm sure there is no way nextis called twice.
它为我节省了一个缩进级别,当我稍后再次阅读代码时,我确信没有办法next被调用两次。
回答by drinchev
next()is part of connect middleware. Callbacks for router flow doesn't care if you return anything from your functions, so return next()and next(); return;is basically the same.
next()是连接中间件的一部分。对于路由器流量回调如果返回从函数什么都不关心,所以return next()和next(); return;基本相同。
In case you want to stop the flow of functions you can use next(err)like the following
如果您想停止功能流,您可以使用next(err)如下所示
app.get('/user/:id?',
function(req, res, next) {
console.log('function one');
if ( !req.params.id )
next('No ID'); // This will return error
else
next(); // This will continue to function 2
},
function(req, res) {
console.log('function two');
}
);
Pretty much next()is used for extending the middleware of your requests.
几乎next()用于扩展请求的中间件。
回答by David
It is best not to use it at all! I explain, and that is what I do also explain it.
最好完全不要使用它!我解释,这就是我所做的也解释它。
The next () function that can have any name and by convention has been set to next. It is indirectly related to the operations (PUT, GET, DELETE, ...) that are generally performed on the same URI resource for example / user /: id
next() 函数可以具有任何名称,并且按照惯例已设置为 next。例如,它与通常在同一 URI 资源上执行的操作(PUT、GET、DELETE 等)间接相关/ user /: id
app.get('/user/:id', function (req,res,next)...)
app.put('/user/:id', function (req,res,next)...)
app.delete('/user/:id', function (req,res,next)...)
app.post('/user/', function ()...)
Now if you look at app.get, app.put and app.delete use the same uri (/ user /: id), the only thing that differentiates them is their implementation. When the request is made (req) express puts the req first in app.get, if any validation you created because that request is not for that controller fails, it passes the req to app.put which is next route in te file and so on. As seen in the example below.
现在,如果您查看 app.get、app.put 和 app.delete 使用相同的 uri (/user/: id),唯一区别它们的是它们的实现。当发出请求时 (req) express 将 req 首先放在 app.get 中,如果由于该请求不是针对该控制器而创建的任何验证失败,它会将 req 传递给 app.put,这是 te 文件中的下一个路由等等在。如下例所示。
app.get('/user/:id', function (req,res,next){
if(req.method === 'GET')
//whatever you are going to do
else
return next() //it passes the request to app.put
//Where would GET response 404 go, here? or in the next one.
// Will the GET answer be handled by a PUT? Something is wrong here.
})
app.put('/user/:id', function (req,res,next){
if(req.method === 'PUT')
//whatever you are going to do
else
return next()
})
The problem lies, that in the end you end up passing the req to all the controllers hoping that there is one that does what you want, through the validation of the req. In the end all controllers end up receiving something that is not for them :(.
问题在于,最终您最终将 req 传递给所有控制器,希望通过对 req 的验证,有一个可以执行您想要的操作。最后,所有控制器最终都会收到不适合他们的东西:(。
So, how to avoid the problem of next ()?
那么,如何避免 next() 的问题呢?
The answer is really simple.
答案很简单。
1-there should only be one urito identify a resource
1-应该只有一个 uri来标识资源
http://IpServidor/colection/:resource/colection/:resourceif your URI is longer than that, you should consider creating a new uri
http://IpServidor/colection/:resource/colection/:resource如果你的 URI 比这个长,你应该考虑创建一个新的 uri
Example http://IpServidor/users/pepe/contacts/contacto1
示例http://IpServidor/users/pepe/contacts/contacto1
2-All operations on this resource must be done respecting the idempotence of the verbs http (get, post, put, delete, ...) so the call to a URI really only has one way of calling
2-必须根据动词http(get,post,put,delete,...)的幂等性来完成对该资源的所有操作,因此对URI的调用实际上只有一种调用方式
POST http://IpServidor/users/ //create a pepe user
GET http://IpServidor/users/pepe //user pepe returns
PUT http://IpServidor/users/pepe //update the user pepe
DELETE http://IpServidor/users/pepe //remove the user pepe
Let's see the code!The concrete implementation that makes us avoid the use of next ()!
让我们看看代码!使我们避免使用next()的具体实现!
In the file index.js
在文件 index.js 中
//index.js the entry point to the application also caller app.js
const express = require('express');
const app = express();
const usersRoute = require('./src/route/usersRoute.js');
app.use('/users', usersRoute );
In the file usersRoute.js
在文件 usersRoute.js 中
//usersRoute.js
const express = require('express');
const router = express.Router();
const getUsersController = require('../Controllers/getUsersController.js');
const deleteUsersController = require('../Controllers/deleteUsersController.js');
router.use('/:name', function (req, res) //The path is in /users/:name
{
switch (req.method)
{
case 'DELETE':
deleteUsersController(req, res);
break;
case 'PUT':
// call to putUsersController(req, res);
break;
case 'GET':
getUsersController(req, res);
break;
default:
res.status(400).send('Bad request');
} });
router.post('/',function (req,res) //The path is in /users/
{
postUsersController(req, res);
});
module.exports = router;
Now the usersRoute.js file does what a file called usersRoute is expected to do, which is to manage the routes of the URI /users/
现在 usersRoute.js 文件做了一个叫做 usersRoute 的文件应该做的事情,即管理 URI /users/ 的路由
//file getUsersController.js
//文件getUsersController.js
//getUsersController.js
const findUser= require('../Aplication/findUser.js');
const usersRepository = require('../Infraestructure/usersRepository.js');
const getUsersController = async function (req, res)
{
try{
const userName = req.params.name;
//...
res.status(200).send(user.propertys())
}catch(findUserError){
res.status(findUserError.code).send(findUserError.message)
}
}
module.exports = getUsersController;
In this way you avoid the use of next, you decouple the code, you gain in performance, you develop SOLID, you leave the door open for a possible migration to microservices and above all, it is easy to read by a programmer.
通过这种方式,您可以避免使用 next,解耦代码,提高性能,开发 SOLID,为可能迁移到微服务敞开大门,最重要的是,它易于程序员阅读。
回答by Manish sharma
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.
调用此函数会调用应用程序中的下一个中间件函数。next() 函数不是 Node.js 或 Express API 的一部分,而是传递给中间件函数的第三个参数。

