【问题标题】:difference between 'done' and 'next' in node.js callbacksnode.js 回调中“完成”和“下一步”之间的区别
【发布时间】:2014-11-27 16:17:57
【问题描述】:

在护照[配置身份验证]文档中,它有一个看起来相当吓人的功能,它使用了神秘的功能“完成”。

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 documentation 中有很多方法可以传递名为 next 的内容。

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

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

【问题讨论】:

  • 一般来说,参数的命名对其功能没有任何影响
  • 所以他们做同样的事情,只是为这两个不同的框架以两种不同的方式记录?
  • 我猜它们都是带有err 参数约定的典型节点回调,所以没有什么“可怕”或“奇怪”。护照是否对您传递的值做不同的事情而不是快递(或者它是否只是传递它们)我不知道,但图书馆的文档应该这样做。
  • 护照回调在verify callback section下的(稍微)更详细的描述
  • return 语句的目的是什么?只是为了避免 else if 吗? done 会返回有用的信息吗?

标签: javascript node.js express passport.js


【解决方案1】:

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

不,它们的用途不同。 Express 用作 node.js 上的应用程序框架,其中护照仅处理 Web 应用程序的身份验证部分。

关于下一个()

next() 是 connect 的一部分,而 connect 又是一个明确的依赖关系。调用 next() 的目的是触发 express 栈中的下一个中间件。

要更轻松地理解next() 概念,您可以查看基于express here 构建的示例应用程序。

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

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

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

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

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

关于完成()

另一方面,

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

的部分
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 的第二个参数是您将从护照策略中调用的done() 的定义。

注意

这里通过我上面提供的两个链接中的示例代码比文档更有助于理解它的行为。我建议你也这样做。

【讨论】:

  • OP 没有询问框架之间的区别(这很明显),而是询问他们使用 next/done 异步回调的方式
  • @Bergi:抱歉,我在其中添加了更多细节。我已经更新了答案。
  • 谢谢,看起来好多了:-) 虽然我不知道为什么req, res, next 都用于done 回调 传递到@987654335 的结果@函数?
  • 在这个特定示例中,他们手动调用身份验证函数,而不是作为路由上的中间件,我认为这就是使用 req, res, next 进行额外函数调用的原因
  • @Bergi: req, res 在护照策略定义中不可用。我们唯一可以访问的是 done 函数,我们可以在其中使用这些变量并实现重定向等逻辑。
【解决方案2】:

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

express 的 next() 想要在第一个参数中出现错误,或者如果没有错误则根本不带参数调用。您还可以在第一个参数中传递路由名称以将控制重定向到,但这不是很常见

【讨论】:

    【解决方案3】:

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

    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/

    【讨论】:

      【解决方案4】:

      next() 将把控制流送到下一个中​​间件,如果有的话。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-26
        • 1970-01-01
        • 2016-03-11
        • 2019-05-15
        • 2014-04-27
        • 2021-10-16
        • 1970-01-01
        相关资源
        最近更新 更多