简体   繁体   English

不带参数的Node.js中间件如何工作?

[英]How does this Node.js middleware work without arguments?

I'm using a function that someone else wrote for express and passport , which defines the middleware(?) as follows: 我正在使用其他人为expresspassport编写的函数,该函数按以下方式定义了中间件(?):

function isLoggedIn(req, res, next) {
    if (req.isAuthenticated()){ 
        return next(); 
    }
    else{
        req.flash('error', 'You need to be logged in to access this page');
        res.redirect('/login');
    }
}

This function is used in the router as follows: 此功能在路由器中的用法如下:

app.get('/page', isLoggedIn, function(req, res){
    // ...
});

What I don't understand is, shouldn't the function be called with parameters req and res ? 我不明白的是,不应该使用参数reqres调用该函数吗? Maybe the callback next is not necessary since it's the next argument of app.get , but how does the function access req and res ? 也许next回调不是必需的,因为它是app.get的下一个参数,但是该函数如何访问reqres I would expect it to be called as follows: 我希望它被称为如下:

app.get('/page', isLoggedIn(req, res), function(req, res){
    // ...
});

How does it work without specifying the arguments? 不指定参数如何工作?

Thanks, 谢谢,

Any functions that you pass to app.get() or app.use() are automatically called with req, res, next passed to them. 传递给app.get()app.use()所有函数都会自动通过req, res, next调用req, res, next传递给它们。 That is how app.get() and app.use() are implemented. 这就是app.get()app.use()的实现方式。

To help you understand, this example: 为了帮助您理解,此示例:

app.get('/page', function(req, res){
    console.log(req.params.foo);
});

is functionally the same as this: 在功能上与此相同:

app.get('/page', myHandler);

function myHandler(req, res) {
    console.log(req.params.foo);
});

You do not want to do something like this: 您不想做这样的事情:

app.get('/page', isLoggedIn(req, res), function(req, res){
    // ...
});

because here you're attempting to execute isLoggedIn(req, res) (when req and res are not yet defined) and then pass it's returned value to app.get() . 因为在这里您尝试执行isLoggedIn(req, res) (当尚未定义reqres时),然后将其返回值传递给app.get() That is not what you want at all. 那根本不是你想要的。 You need to pass a function reference to app.get() and it will supply the parameters when it calls the function. 您需要将函数引用传递给app.get() ,它将在调用函数时提供参数。 Any time you put () after a function in Javascript, that means you want to execute it NOW. 任何时候将()放在Javascript函数之后,都意味着您现在想执行它。 But, if you just pass the function's name, then that is a function reference which can be stored and called later as desired. 但是,如果仅传递函数名称,则该函数引用可以存储并在以后根据需要调用。

This code example is analogous to this: 此代码示例与此类似:

var result = isLoggedIn(req, res);

app.get('/page', result, function(req, res){
    // ...
});

Besides the fact that this would cause an error because req and res are not defined at program start time when this would execute, hopefully you can see that you don't want to execute isLoggedIn() now. 除了由于执行程序时未在程序启动时定义reqres而导致错误的事实之外,希望您可以看到自己现在不想执行isLoggedIn() Instead, you just want to pass a function reference so Express can call it later. 相反,您只想传递一个函数引用,以便Express稍后可以调用它。

In this code 在这段代码中

app.get('/page', isLoggedIn, function(req, res){
    // ...
});

The app.get method is being called with three arguments: 正在使用三个参数调用app.get方法:

  1. the route to the page: /page 页面的路由: /page
  2. the middleware function 中间件功能
  3. the request handler function 请求处理函数

Basically, this code is telling the express framework that when a GET request is received for the /page path, then it should call two functions: first, the middleware function and second the handler function. 基本上,这段代码告诉Express框架,当收到针对/page路径的GET请求时,它应该调用两个函数:第一个是中间件函数,第二个是处理程序函数。

The important thing to note here is that it is the framework doing the work. 这里要注意的重要一点是它是完成工作的框架。 The framework is going to call the middleware function, then it's going to call the handler function. 该框架将调用中间件函数,然后将调用处理程序函数。

What I don't understand is, shouldn't the function be called with parameters req and res? 我不明白的是,是否应该不使用参数req和res调用该函数?

It will be called with these arguments, somewhere inside the get function. get函数内部的某个位置使用这些参数调用它。 Suppose this is the simplified get , implemented as 假设这是简化的get ,实现为

// a super simple get that will expect a function
// and call the function with two arguments
function get( f ) {
    var res = 1, req = 1;
    f( res, req );
}

There are multiple ways of passing a function to get . 有传递功能的多种方式get For example, you pass an anonymous function 例如,您传递一个匿名函数

get( function( res, req ) {
   return res + req;
}

You can also pass a named function defined elsewhere 您还可以传递在其他地方定义的命名函数

function isLoggedIn( res, req ) {
   return res + req;
}

get( isLoggedIn );

This however, is not what you'd expect: 但是,这不是您期望的:

get( isLoggedIn( res, req ) );

The problem here is that 这里的问题是

isLoggedIn( res, req )

is no longer a function declaration . 不再是函数声明 It is an invocation and the result of this invocation depends on what res and req are. 这是一个调用调用的结果取决于resreq是什么。 With some luck, the invocation can even yield a number value, which means that get is no longer invoked with function as an argument but with the result of function invocation. 运气好的话,该调用甚至可以产生一个数字值,这意味着get不再使用function作为参数来调用,而是使用function调用的结果来调用。

In short, to pass a named function to another function, you don't specify its arguments. 简而言之,要将命名函数传递给另一个函数,您无需指定其参数。 The supposed syntax that would allow this doesn't even make sense because it would be indistinguishable from a syntax of actual function invocation (ie the value of the call). 假定的允许这样做的语法甚至没有意义,因为它与实际函数调用的语法(即调用的值)没有区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM