'完成'和'接下来'在node.js回调中

difference between 'done' and 'next' in node.js callbacks

本文关键字:js node 回调 接下来 完成      更新时间:2023-09-26

在passport[configure authentication]文档中,它有一个看起来相当可怕的函数,它使用了神秘的函数"done"

passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); }
      if (!user) {
        return done(null, false, { message: 'Incorrect username.' });
      }
      if (!user.validPassword(password)) {
        return done(null, false, { message: 'Incorrect password.' });
      }
      return done(null, user);
    });
   }
));

现在,在express文档中,有相当多的方法可以传递名为next的东西。

app.use(function(err, req, res, next){
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

这就是express和passport这两个框架之间的区别吗?还是他们在做两件不同的事情?

这就是express和passport这两个框架之间的区别吗

不,它们的用途不同。Express被用作node.js上的应用程序框架,其中as passport只处理web应用程序的身份验证部分。

关于next()

next()是connect的一部分,inturn是一个表达式依赖项。调用next()的目的是触发express堆栈中的下一个中间件。

为了更容易地理解next()概念,您可以在此处查看一个基于express构建的示例应用程序

正如您在所指向的行中看到的,应用程序使用路由级中间件来检查用户是否登录。

app.get('/account', ensureAuthenticated, function(req, res){

这里ensureAuthenticated是像一样在底部定义的中间件

function ensureAuthenticated(req, res, next) {
  if (req.isAuthenticated()) { return next(); }
  res.redirect('/login')
}

正如您所看到的,如果用户通过了身份验证,函数会调用next()并将控制权传递给上面写的路由处理程序中的下一层,否则即使不调用next() ,它也会重定向到另一个路由

关于done()

done()用于触发我们为护照身份验证编写的返回url处理程序。要了解更多关于如何完成的工作,您可以查看passport此处的代码示例,并查看标题为自定义回调的部分

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);
});

这里,passport.authenticate的第二个参数是您将从passport策略调用的done()的定义。

注释

在这里,通过我上面提供的两个链接中的示例代码,在理解其行为方面比文档有很大帮助。我建议你也这样做。

passport的done()希望您为第一个参数传递一个错误(或null),并将一个用户对象作为第二个参数。

express的next()希望在第一个参数中出现错误,或者在没有错误的情况下完全不使用参数进行调用。您也可以在第一个参数中传递将控制重定向到的路由的名称,但这不是很常见的

让我们备份,因为我认为您可能有一些困惑。

Express是一个web应用程序框架。从广义上讲,它负责引导用户访问资源。

Passport是一个身份验证框架。它负责确保允许用户访问所述资源。

在这两个框架中都有中间件的概念。中间件基本上是广义的控制流。例如,在某些Express框架中,您可以说:

  1. 请求路由/user/:x 时,确保参数x有效

    • 如果有效,则next()-->,这意味着转到下一个中间件函数()
  2. 确保用户有会话等

  3. 当所有中间件都执行完毕后,我们执行应用程序

例如,

router.get('/', function(req, res) { // when the '/' route is requested
    res.render('index', { title: 'Express' }); // send index.html
});

在Passport中,他们也使用中间件的思想,但是,他们使用done()而不是next()而且有点复杂。有关详细信息,请参阅此页面
http://toon.io/understanding-passportjs-authentication-flow/

next()将获得到下一个中间件的控制流(如果有)。

在Passport.js中,调用done()将使流跳回到passport.authenticate()。它传递了错误、用户和附加信息对象(如果已定义)。

在其他情况下,done()将把控制流带到它在其中使用的函数之后的下一个函数。