我是Node和Express的新手以及与使用节点构建网络应用程序以及request
和response
参数一起使用的其他图层让我感到困惑。我的困惑在于,这两个参数通常存在于函数中,但通常不会声明其中的一个或两个。此外,大多数情况下会引入其他参数,例如'next'
或其他参数。例如,我有一个API的以下路由器:
router.route('/teams')
// create a team at POST http://localhost:8080/api/teams
.post(function(req, res) {
var team = new Team();
team.name = req.body.name;
team.location = req.body.location;
// save the new team and check for errors
team.save(function(err) {
if (err) {
res.send(err);
};
res.json({ message: 'Team created!' });
});
})
// GET all the teams at GET http://localhost:8080/api/teams
.get(function(req, res) {
Team.find(function(err, teams){
if (err) {
res.send(err);
};
res.json(teams);
});
});
.post
和.get
都会调用req
和res
作为参数的函数,但永远不会使用req
。那么如果他们没有定义和使用或者没有在完全不同的订单中使用,那么该函数如何知道如何处理req或res?或者,如果我将它们命名为完全不同的东西?
请求和回复究竟发生了什么?对不起我的无知。我已经阅读了文档,但没有点击。
感谢。
答案 0 :(得分:6)
当您使用expressApp.use('/some/route', myRouteHandler);
时,Express将侦听该路由的请求,当它被命中时,它将调用您提供的功能(回调)。它将为它提供三个参数:请求和响应,以及下一个。 (实际上可能是四个,但是让事情变得简单。)
所以,你的回调可能是这样定义的:
function myRouteHandler(a, b, c) {
// do stuff
};
或者像这样:
function myRouteHandler(req, res, next) {
// stuff
}
或简单地说:
function myRouteHandler() {
// stuff
}
无论你做什么,都无所谓。当应用程序启动时,express会监听请求。
当其中一个匹配路线(/some/route
)时,快递将在其内部工作中调用您提供的功能,如下所示:
myRouteHandler(requestObject, responseObject, nextMiddleware);
因此,在第一种情况下,您可以使用req访问请求(例如,请求标头,完整网址,来电者IP地址或类似信息)。在第二种情况下,您可以通过拨打电话来访问它。在第三种情况下,您可以使用参数[0]。
按照惯例,人们会使用以下格式:myCallback(req, res)
并知道Express会将请求对象作为第一个参数,并将响应作为第二个参数。响应对象实际上有一个方法end(),因此您可以结束请求。如果还有next()对象,则可以调用下一个中间件。
假设您的路线定义如下:
app.use('/api/users', checkAuthorizationHandler);
app.use('/api/users', makeSureTheIPisFromOurInternalNetwork);
app.use('/api/users', nowHandleTheResponse);
每个处理程序都获得第三个参数。如果你命名它,你通常在你的函数声明中称它为'next'参数。这意味着,顺序的下一个功能。
假设您的function checkAuthorizationHandler(req, res, next)
将检查req.headers('auth')令牌,如果没问题,它将在函数体中调用next()
。
然后调用function makeSureTheIPisFromOurInternalNetwork(a, b, c)
。它将检查a.ip是否为LAN IP地址并调用c();
最后,您的function nowHandleTheResponse()
会找到所有用户,并使用用户的JSON对象进行回复:arguments[1].json([user1, user2, user3]);
所以,第一个param是表达给你的东西,它是请求,第二个是响应,第三个是下一个中间件函数。无论你怎么称呼他们,他们都在那里。
P.S。您还可以使用 four 参数声明中间件:
function(error, req, res, next);
Express会实际检查你的功能,如果它发现你有四个参数而不是两个或三个,它会给你链中早期运行的中间件抛出的任何错误。这意味着,如果你的checkAuthHandler说下一个(新的错误('未授权'));,你的下一个函数可能会检查该错误,如果它存在,则不给出结果。然而,检测错误的中间件通常会重新发送('某些错误消息');
如果我没有让你感到困惑,那就说,我得到的更多来自:)
答案 1 :(得分:4)
这是框架惯例。第一个参数是request
,第二个参数是response
。如果您要声明中间件(.use
),则第三个参数是链中的next
中间件。
只要您知道订单,就可以根据需要为这些变量命名。您可以使用.post(function(a,b) {});
,然后请求由变量a
表示,响应由变量b
表示。
如果由于某种原因,您不需要请求,只需要响应,您仍然必须有第一个参数,因为响应由第二个参数表示。
在javascript中,没有类似Java中的方法重载(例如,这可能是你从中获得混淆的地方)。函数由其名称表示,而不是由多少个参数表示。这是一个简单的例子:
function logToConsole(level, message) {
if (!message) {
message = level;
level = 'INFO';
}
console.log('['+level+']', message);
}
logToConsole('My message'); // prints out: "[INFO] My message"
logToConsole('WARN', 'My message'); // prints out: "[WARN] My message"
您是否注意到我们如何根据level
的存在为message
定义默认值?
希望这能澄清一些事情。
答案 2 :(得分:1)
Request
,response
和next
将传递给所有中间件功能。 request
对象包含有关HTTP request
的信息,response
对象用于处理request
。 Expressjs documentation详细说明了这些对象。 next()
调用用于调度程序,中间件函数可能会或可能不会调用next()
,具体取决于用法。 Next
只是调用以下中间件。
以下是使用next()
:
function helloWorld(req,res,next){
console.log('Hello, world!');
next();
}
// This function doesn't call next(), therefore it will
// not call the subsequent middleware in the dispatcher
function goodbyeWorld(req,res,next){
console.log('Goodbye, world!');
}
app.use(helloWorld);
app.use(goodbyeWorld);
输出:
你好,世界!
再见,世界!
现在让我们重新排序中间件
app.use(goodbyeWorld);
app.use(helloWorld);
输出:
再见,世界!
未调用helloWorld
函数。请注意中间件订单和next()
函数调用的重要性。