【问题标题】:Express-validator does not return object in async validationExpress-validator 在异步验证中不返回对象
【发布时间】:2016-05-24 17:51:44
【问题描述】:

我正在使用本地策略使用 express-validator 和 passport.js 验证登录表单:

login: function() {
  passport.use('local-login', new LocalStrategy({
    passReqToCallback: true
  },
    function(req, username, password, done) {
      req.check('username', 'Incorrect user and/or password.').doesUserExists(password);
      req.check('password', 'Password cannot be empty.').notEmpty();

      req.asyncValidationErrors(true)
      .then(function(user) {
        return done(null, user);
      })
      .catch(function(errors) {
        if (errors) return done(null, false, req.flash('error', errors));
      });
    }
  ));
}

函数doesUserExists()是一个自定义的异步验证,它查询用户,将提供的密码与数据库中的哈希密码进行比较,然后解析:

doesUserExists: function(username, password) {
  return new Promise(function(resolve, reject) {
    User.findOne({ username: username })
    .then(function(user) {
      if (user) return user;
      if (!user) reject(user);
    })
    .then(function(user) {
      user.comparePassword(password, function(error, isMatch) {
        if (isMatch) return user;
        else reject(user);
      });
      resolve(user);
    })
    .catch(function(error) {
      if (error) reject(error);
    });
  });
}

到目前为止,它工作正常,除非用户和密码匹配,并且 promise 被解析,没有对象(用户)返回到 req.asyncValidationErrors() 函数,防止其 .then() 块重定向到用户资料。

我必须补充一点,我对 Promise 很陌生,不确定我所期望的是否会发生。也许对它的工作原理的一些误解导致我错误地思考。

更新

现在,我决定对已验证的用户/密码进行另一个数据库查询:

req.asyncValidationErrors(true)
  .then(function() {
    User.findOne({ username: username })
    .then(function(user) {
      return done(null, user);
    });
  })
  .catch(function(errors) {
    if (errors) {
      return done(null, false, req.flash('error', errors));
    }
  });

额外的数据库查询并不优雅,但是...

【问题讨论】:

    标签: javascript node.js validation


    【解决方案1】:

    只要返回 User.find 返回的 Promise,就不需要创建新的 Promise:

    doesUserExists: function(username, password) {
        return User.findOne({ username: username })
        .then(function(user) {
          if (user) {
            // Also here is a mistake because we can't return inside 
            // the comparePassword callback, and that's why user is not get back
            user.comparePassword(password, function(error, isMatch) {
              if (isMatch) return user;
              else throw new Error('my error');
            });
          }
          else throw new Error('my error');
        });
    }
    // Now use it as follows
    req
    .check('username', 'Incorrect user and/or password.')
    .doesUserExists(username, password)
    .then(function(user){/* user authenticated */})
    .catch(function(error){/* user not atuhenticated */});
    

    所以我猜你可以稍后比较密码并解决问题:

    doesUserExists: function(username, password) {
        return User.findOne({ username: username })
        .then(function(user) {
          if (user) return user;
          else throw new Error('my error');
        });
    }
    // Now use it as follows
    req
    .check('username', 'Incorrect user and/or password.')
    .doesUserExists(username, password)
    .then(function(user){
      /* From here, user was found */
      user.comparePassword(password, function(error, isMatch) {
        if (isMatch){ /* Do whatever with the user authenticated */ }
        else { /* Do whatever you want when password don't match */ }
      });
    })
    .catch(function(error){/* user not found */});
    

    如果你做不止一个异步验证,我建议你使用Promise.all() make 来执行并行异步函数。

    【讨论】:

    • 感谢您的回答。我不知道 Mongoose 查询是承诺。这可能在以后有用。我尝试了您的实现,但由于某种原因,express-validator 抛出错误req.check().then() is not a function。感谢Promises.all()的提示,我正在考虑但不确定是否使用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 2013-07-11
    • 1970-01-01
    • 2020-06-29
    相关资源
    最近更新 更多