使用额外的括号调用对象方法

invoking object methods with extra parenthesis

我正在查看 passport.js 文档,我注意到这段代码:

app.get('/login', function(req, res, next) {

  passport.authenticate('local', function(err, user, info) {

    if (err) { return next(err); }

    if (!user) { return res.redirect('/login'); }

    req.logIn(user, function(err) {

      if (err) { return next(err); }

      return res.redirect('/users/' + user.username);

    });

  })(req, res, next);

});

倒数第二行的 (req, res, next) 是怎么回事?

据我所知,这不是 IIFE 的正确语法或上下文,并且 req、res 和 next 应该已经可用于身份验证函数。

谢谢,

扎基尔

passport.authenticate() returns一个中间件函数。

即它有签名 fn(req, res, next).

当你想在路由中 运行 它时,你必须自己调用它并将这些参数传递给它,以便它可以访问请求中的数据、操作响应等。

app.get('/login', function(req, res, next) {
  passport.authenticate('local')(req, res, next);
});

这 运行 是您的本地策略,并执行其配置的任何操作。

你刚刚写过这个吗:

app.get('/login', function(req, res, next) {
  passport.authenticate('local')();
});

reqresnextauthenticate函数不可用。

简单地调用一个函数并不能让它访问调用点范围内的变量。例如,这不起作用:

function addOne() {
  x++;
}

app.get('/', function() {
  var x = 99;
  addOne();
})

当您定义一个函数时,该函数可以在您调用它的定义站点whenever/wherever范围内访问变量。

您的代码段在本地策略具有 运行 之后传入(定义)一个回调 运行 ,它允许您在本地策略成功或失败后 运行 任意逻辑来验证用户。

app.get('/login', function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    if (err) return next(err);
    if (!user) return res.redirect('/login'); 
    req.logIn(user, function(err) {
      if (err) return next(err);
      return res.redirect('/users/' + user.username);
    });
  })(req, res, next);
});

此回调可以访问 reqresnext,因为在定义回调函数时它们在范围内。

但是,在调用passport的authenticate函数时,仍然需要传递reqresnext,这样它才能访问它们。该函数已在库中定义,因此与定义的回调函数不同,它没有捕获路由中的 resresnext 变量。

当定义的回调函数是 运行 时,范围内的 req/res 变量可能已经被 authenticate [=66= 的局部策略中发生的任何事情改变了]s。回调函数开始读取变量的状态并一并拥有最终决定权——它本质上是 post- 处理 authenticate 方法的结果,如果 Passport 已构建,则允许您完全自由地编写自己的逻辑-in 选项不够。

调用站点与函数定义站点之间的作用域行为差异导致了令人困惑的代码段。