Reputation: 2301
Disclaimer: I am a newb web dev.
I am creating a registration page. There are 5 input fields, with 3 of them (username, password, and email) requiring that they pass various forms of validation. Here is the code:
router.post('/register', function (req, res, next) {
user.username = req.body.username;
user.profile.firstName = req.body.firstName;
user.profile.lastName = req.body.lastName;
user.password = req.body.password;
user.email = req.body.email;
User.findOne({email: req.body.email}, function(err, existingEmail) {
if(existingEmail) {
console.log(req.body.email + " is already in use")
} else {
User.findOne({username: req.body.username}, function(err, existingUsername) {
if(existingUsername) {
console.log(req.body.username + " is already in use");
} else {
user.validate({password: req.body.password}, function(err) {
if (err) {
console.log(String(err));
} else {
user.save(function(err, user) {
if (err) {
return next(err);
} else {
return res.redirect('/')
}
})
}
});
}
});
}
});
});
Basically it first checks to see if it is a duplicate e-mail; if it is a duplicate e-mail, it says so in the console.log. If it isn't a duplicate e-mail, it then checks the username.... and then goes onto the password.
The issue is that it does this all one at a time; if the user inputs an incorrect email and username, it will only say that the email is incorrect (it won't say that both the email and username are incorrect).
How can I get this to validate all 3 forms at the same time?
Upvotes: 0
Views: 748
Reputation: 2755
You can use async to run them in parallel and it will also make your code cleaner and take care of that callback hell:
var async = require('async');
async.parallel([
function validateEmail(callback) {
User.findOne({email: req.body.email}, function(err, existingEmail) {
if(existingEmail) {
callback('Email already exists');
} else {
callback();
}
}
},
function validateUsername(callback) {
User.findOne({username: req.body.username}, function(err, existingUsername) {
if(existingUsername) {
callback('Username already exists');
} else {
callback();
}
}
},
function validatePassword() {
user.validate({password: req.body.password}, function(err) {
if(err) {
callback(err);
} else {
callback();
}
}
}
], function(err) {
if(err) {
console.error(err);
return next(err);
} else {
user.save(function(err, user) {
if (err) {
return next(err);
} else {
return res.redirect('/');
}
});
}
}
);
This way, all the validation methods inside the array will be run in parallel and when all of them are complete the user will be saved.
Upvotes: 1
Reputation: 17721
If you use else
statements, you choose to make checks individually (one at a time) by design.
To achieve an 'all at once' behaviour, I would not use else
statements (where possible, i.e. errors ar not fatal for next checks), but would do all tests in the same block, and would fill an object like this:
errors: {
existingEmail: false,
existingUserName: false,
invalidUserName: false,
wrongPassword: false,
...
};
And then I'd use it in the form to show user all errors together...
Something like this:
var errors = {};
if (existingEmail) {
console.log(req.body.email + " is already in use");
errors.existingEmail: true;
}
User.findOne({username: req.body.username}, function(err, existingUsername) {
if (existingUsername) {
console.log(req.body.username + " is already in use");
errors.existingUsername: true;
} else {
user.validate({password: req.body.password}, function(err) {
if (err) {
console.log(String(err));
errors.invalidUsername = true;
} else {
user.save(function(err, user) {
if (err) {
return next(err);
} else {
return res.redirect('/')
}
})
}
});
}
});
Upvotes: 0