简体   繁体   中英

How to run multiple queries, express/mongoose validation

I am trying to validate a sign in form. Right now I am struggling to get the username and email validation parts to work correctly.

Both of these fields are supposed to be unique, as specified in my schema.

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

I also have a statics method defined on the schema.

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

The code is supposed to to see if a username and email already exists in the database before attempting to save through a callback function. However, the method continuously returns isValid = true, when I test it. I assume this is due to Node's asynchronous nature. If so what is a good way to handle this sort of thing?

Use Promise or async .

Here is a sample code using Promise . I have broken up the validation into smaller functions (each returns a promise ) and then chained these promises.

Ideally it would be simpler to return a promise from the main function, but then keeping in mind that your remaining code is already setup with callback , next etc, I have kept the callback way. Usage example is at the end of the code.

Also, do you really need next? You have a callback!

See usage example at the end of the code.

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

Hope this helps you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM