【问题标题】:How does this Node.js middleware work without arguments?这个 Node.js 中间件如何在没有参数的情况下工作?
【发布时间】:2017-02-06 02:59:17
【问题描述】:

我正在使用别人为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');
    }
}

该函数在路由器中使用如下:

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

我不明白的是,不应该用参数reqres调用函数吗?也许回调next 是不必要的,因为它是app.get 的下一个参数,但是函数如何访问reqres?我希望它被如下调用:

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

如果不指定参数,它是如何工作的?

谢谢,

【问题讨论】:

    标签: javascript node.js express


    【解决方案1】:

    您传递给app.get()app.use() 的任何函数都会被自动调用,其中req, res, next 传递给它们。这就是app.get()app.use() 的实现方式。

    为了帮助你理解,这个例子:

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

    在功能上与此相同:

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

    你不想做这样的事情:

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

    因为在这里您尝试执行isLoggedIn(req, res)(当reqres 尚未定义时)然后将其返回值传递给app.get()。这根本不是你想要的。您需要将函数引用传递给app.get(),它会在调用函数时提供参数。任何时候你把() 放在 Javascript 中的一个函数之后,这意味着你想现在就执行它。但是,如果您只是传递函数的名称,那么这是一个函数引用,可以在以后根据需要存储和调用。

    此代码示例与此类似:

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

    除了这会导致错误,因为reqres 没有在程序开始时定义,这将执行,希望你能看到你现在不想执行isLoggedIn()。相反,您只想传递一个函数引用,以便 Express 可以稍后调用它。

    【讨论】:

    • 谢谢!关于reqres 还没有出现的好处。所以如果我要定义自己的中间件,它应该总是有这三个参数吗?如果我想添加另一个参数怎么办?无论如何,这回答了我的问题,所以我会在几分钟内接受它。
    • @jeff - 您不能将自己的参数添加到中间件。中间件将获得(req, res, next) 作为参数。如果您要调用的函数需要比这更多的参数,那么您可以使用三个参数创建一个标准中间件函数,然后从其中调用您的另一个函数并传递您自己的函数所需的任何参数。
    • 是的。我刚刚发现-我认为-同样的事情here
    • @jeff - 是的,这个例子有点棘手 - 一个函数返回一个函数。您可能不需要这样做。您也许可以将function(req, res, next) { myFunc(req, res, next, someOtherArg);} 作为您的中间件。
    【解决方案2】:

    在这段代码中

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

    使用三个参数调用app.get 方法:

    1. 页面路径:/page
    2. 中间件功能
    3. 请求处理程序函数

    基本上,这段代码告诉 express 框架,当接收到对 /page 路径的 GET 请求时,它应该调用两个函数:第一个是中间件函数,第二个是处理函数。

    这里要注意的重要一点是,它是由框架来完成的。框架会调用中间件函数,然后调用处理函数。

    【讨论】:

      【解决方案3】:

      我不明白的是,函数不应该用参数req和res调用吗?

      它将get 函数内部的某个位置使用这些参数调用。假设这是简化的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 );
      }
      

      有多种方法可以将函数传递给get。例如,你传递一个匿名函数

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

      你也可以传递在别处定义的命名函数

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

      然而,这不是你所期望的:

      get( isLoggedIn( res, req ) );
      

      这里的问题是

      isLoggedIn( res, req )
      

      不再是一个函数声明。这是一个调用,调用的结果取决于resreq 是什么。运气好的话,调用甚至可以产生一个数值,这意味着 get 不再使用函数作为参数调用,而是使用函数调用的结果

      简而言之,要将命名函数传递给另一个函数,您无需指定其参数。允许这样做的假定语法甚至没有意义,因为它与实际函数调用的语法(即调用的值)无法区分。

      【讨论】:

        猜你喜欢
        • 2022-01-14
        • 2013-05-02
        • 1970-01-01
        • 1970-01-01
        • 2023-02-16
        • 2013-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多