我在这个注册路径中有点困惑。你可以看到我在向db发送数据之前执行了一些验证检查。
首先,我检查表单中的空白字段,然后检查记录中的用户名和电子邮件是否存在以及最后一次密码确认。 所有这些都运行正常,但由于数据库查询应用程序的异步行为每次都崩溃。
/* POST Register User */
router.post('/register',function(req,res,next){
let user = req.body;
//checking for empty field in a form
for(let key in user){
if(user[key] === ""){
return next(mid.error("All fields are required to fill"));
}
}
User.findOne({username:user.username})
.exec(function(err,user){
if(err){
return next(mid.error("Something went wrong"));
}
if(user){
return next(mid.error("Username already exist"));
}
});
User.findOne({email:user.email})
.exec(function(err,user){
if(err){
return next(mid.error("Something went wrong"));
}
if(user){
return next(mid.error("Email already exist"));
}
});
//matching password
if(user.password !== user.confirm){
return next(mid.error("Password not matched.Try again !"));
}
//save data in object
let userData = {
username : user.username,
email : user.email,
password : user.password
};
//save data in database
User.create(userData,function(err,user){
if(err){
return next(mid.error("Something went wrong.Try again !!!"));
} else {
req.session.userID = user._id;
return res.redirect('/home');
}
});
});
有没有办法摆脱这个?
答案 0 :(得分:1)
如您所述,查询为Asynchronous
。
在这种情况下,正在处理findOne
个调用,因为findOne
调用本身是Synchronous
,当其中一个查询首先完成并执行回调时会导致错误。然后,您的回调将返回并将所有内容传递给下一个中间件。
在第一次查询完成后,您可以将所有想要的内容放入回调中。在这种情况下:
User.findOne({username:user.username})
.exec(function(err, foundUser){
if(err){
return next(mid.error("Something went wrong"));
}
if(foundUser){
return next(mid.error("Username already exist"));
}
User.findOne({email:user.email})
.exec(function(err,foundUser){
if(err){
return next(mid.error("Something went wrong"));
}
if(foundUser){
return next(mid.error("Email already exist"));
}
//HERE GOES ALL OTHER CODE THAT SHOULD HAPPEN AFTER THE QUERIES
});
});
请注意,我在回调中重命名了
user
变量,这样它就不会与用于查询的user
对象冲突!
将来,或者对于更复杂的用例,我建议使用Promises
来避免像这样的深层嵌套回调。