Node js function requires a return value but value comes from callback so cannot be returned
Problem
Apologies for the confusing title, I will attempt to explain
I am using node.js with express-form and the custom validation function like so:
app.post('/register', form(
field("username").trim().required().custom(function(value) {
//Works correctly
if (!user.validUsername(value)) {
throw new error("Invalid username");
}
//Does not work due to callback
user.uniqueUsername(value, function(uniqueUsername) {
if (!uniqueUsername) {
//Not unique, throw error
throw new Error("username is already taken");
//Could be subsituted for return "whatever"; and it would still be the same problem
}
});
}),
registerAttempt);
};
// ...
//Example function for brevity
user.uniqueUsername = function(username, callback) {
User.findOne({username: username}, function(err, user) {
if (err) { throw err; }
callback(user === null);
});
}
I need a way to restructure this so the .custom(function(value) { .. }) doesn't finish executing until I have received the Callback but I have no idea how I could do it, if at all.
EDIT: corrected error
Solution
It looks like express-form doesn't support asynchronous validations, so the only way to that is implement custom middleware. It can look like this:
app.post('/register',
function (req, res, next) { //here it goes
user.uniqueUsername(req.body.username, function(uniqueUsername) {
req.body.uniqueUsername = uniqueUsername; //we can't do anything about it yet
next();
});
},
form(field('username').trim().required().custom(function(value) {
if (!user.validUsername(value)) {
throw new error("Invalid username");
}
}),
field('uniqueUsername').custom(function(value) {
if (!value) {
throw new Error("username is already taken");
}
}),
registerAttempt);
It can be used as generic workaround for express-form being unable to make async validations: we pull all the data we need in a separate middleware and inject it as new fields to be then validated by express-form.
Discussion
View additional discussion.