我正在尝试验证登录表单。现在,我正在努力让用户名和电子邮件验证部分正常工作。
这两个字段应该是唯一的,正如我的架构中所指定的那样。
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的异步性质。如果是这样,处理这类事情的好方法是什么?
答案 0 :(得分:2)
以下是使用Promise
的示例代码。我已将验证分解为较小的函数(每个函数返回一个promise
),然后链接这些承诺。
理想情况下,从main函数返回一个promise更简单,但是请记住,您的剩余代码已经设置为callback
,next
等,我保持了回调方式。用法示例位于代码的末尾。
另外,你真的需要下一个吗?你有一个回调!
请参阅代码末尾的用法示例。
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);
希望这会对你有所帮助。