如何运行多个查询,表达/猫鼬验证

时间:2017-01-24 07:40:34

标签: node.js forms mongodb express mongoose

我正在尝试验证登录表单。现在,我正在努力让用户名和电子邮件验证部分正常工作。

这两个字段应该是唯一的,正如我的架构中所指定的那样。

var userSchema = new mongoose.Schema({
  username: {type:String,required:true,trim:true,unique:true},
  password:{type:String,required:true},
  email:{type:String,required:true,unique:true},
  verified:{type:Boolean,required:true},
  dateCreated:{type:Date,default:Date.now}
});

我还有一个在架构上定义的静态方法。

userSchema.statics.validateSignUp = function(username,useremail,password,passwordConfirmation,callback,next){
  var isValid = true;
  var User = this;
  var errorObject = {};
  if(username.trim().length >= 5){
    //check to see if username already exists
    User.findOne({'username': username}).exec(function(err,user){
        if(err){
          return next(err);
        }
        if(user){
          isValid = false;
          errorObject.username = 'Username is already taken.';
        }
      });
  }else{
    isValid = false;
    errorObject.username = 'Username must be at least 5 chars long.';
  }

  //check to see if password is greater than 5 characters
  //if not add to responseJson errors
  if(password.length < 5){
    isValid = false;
    errorObject.password = 'Password must be at least 5 chars long.';
  }

  //check password confirmation
  if(password !== passwordConfirmation){
    isValid = false;
    errorObject.passwordConfirm = 'Passwords do not match.';
  }

  //check email against regex
  var emailRe = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  if(emailRe.test(useremail)){
    User.findOne({'email':useremail}).exec(function(err,user){
        if(err){
          return next(err);
        }
        if(user){
          isValid = false;
          errorObject.email = 'User with this email already exists.';
        }
      });
  }else{
    isValid = false;
    errorObject.email = 'Email is not valid.';
  }
  if(!isValid){
    console.log('not valid')
    return errorObject;
  }else{
    console.log('valid')
    callback()
  }
}

代码应该是在尝试通过回调函数保存之前,查看数据库中是否已存在用户名和电子邮件。但是,当我测试它时,该方法连续返回isValid = true。我认为这是由于Node的异步性质。如果是这样,处理这类事情的好方法是什么?

1 个答案:

答案 0 :(得分:2)

使用Promiseasync

以下是使用Promise的示例代码。我已将验证分解为较小的函数(每个函数返回一个promise),然后链接这些承诺。

理想情况下,从main函数返回一个promise更简单,但是请记住,您的剩余代码已经设置为callbacknext等,我保持了回调方式。用法示例位于代码的末尾。

另外,你真的需要下一个吗?你有一个回调!

请参阅代码末尾的用法示例。

userSchema.statics.validateSignUp = function (username, useremail, password, passwordConfirmation, callback, next) {

    var isValid = false;
    var User = this;
    var errorObject;

    const checkUsername = function () {
        return new Promise(function (resolve, reject) {
            errorObject.username = 'Username must be at least 5 chars long.';
            if (username.length < 5) return resolve(errorObject);

            User.findOne({ username: username }).exec(function (err, user) {
                if (err) return reject(err);
                if (user) errorObject.username = 'Username is already taken.';
                return resolve();
            });
        });
    };

    const checkPassword = function () {
        return new Promise(function (resolve, reject) {

            if (password.length < 5) {
                errorObject.password = 'Password must be at least 5 chars long.';
                return resolve();
            }

            if (password === passwordConfirmation) return resolve();

            errorObject.password = 'Passwords do not match.';
            resolve();
        });
    };

    const checkEmail = function () {
        return new Promise(function (resolve, reject) {

            var emailRe = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

            if (!emailRe.test(useremail)) {
                errorObject.email = 'Email is not valid.';
                resolve();
            }

            User.findOne({ 'email': useremail }).exec(function (err, user) {

                if (err) return reject(err);

                if (user) {
                    errorObject.email = 'User with this email already exists.';
                    resolve();
                }

                isValid = true;
                resolve();
            });

        });
    };

    checkUsername()
        .then(checkPassword)
        .then(checkEmail)
        .then(function () {

            // if (isValid) console.log('valid');
            // else console.log('not valid');

            callback(errorObject, isValid);

        })
        .catch(function (err) {
            next(err);
        });
};


//USAGE EXAMPLE:

// userModel.validateSignUp('foo', 'foo@bar.com', 'bar', 'bar', function (err, valid) {

//     if (err) return console.log(err);

//     if (valid) console.log('valid');
//     else console.log('not valid');

// }, next);

希望这会对你有所帮助。