Javascript 如何链接条件异步回调?
在node.js express项目中,我想为管理员用户实现切换到用户功能。管理员可以在框中键入用户名或用户id。下面是处理此请求的代码。问题是,如果第一次数据库调用失败,我需要用另一种查询重复它,然后再继续使用登录代码。如何在调用Javascript 如何链接条件异步回调?,javascript,node.js,express,asynchronous,Javascript,Node.js,Express,Asynchronous,在node.js express项目中,我想为管理员用户实现切换到用户功能。管理员可以在框中键入用户名或用户id。下面是处理此请求的代码。问题是,如果第一次数据库调用失败,我需要用另一种查询重复它,然后再继续使用登录代码。如何在调用req.login之前添加条件异步调用 router.route('/switchuser') .post(function (req, res) { mongoose.model('Users').findById(req.body.idOr
req.login
之前添加条件异步调用
router.route('/switchuser')
.post(function (req, res) {
mongoose.model('Users').findById(req.body.idOrName, function (err, user) {
if (!user) {
mongoose.model('Users').findOne({ username: req.body.idOrName }, function (err, user_) {
user = user_;
if (err) {
res.status(404);
res.send("User not found " + err);
}
});
}
req.login(user, function (err) {
if (err) {
res.status(404);
res.send("There was a problem switching the user: " + err);
}
else {
res.format({
html: function () {
res.redirect("/");
}
});
}
})
});
});
你正在经历地狱。当ID找不到用户时,启动第二个回调。问题是您的login-as方法在第二个回调之外执行,这意味着它不等待响应。回调地狱会很快导致大量重复代码。一种解决方案是将常见的代码位提取到函数中。下面是一个示例,说明了您可以如何做到这一点。请注意,
loginAs
可以在两个不同的位置调用,这取决于用户是通过ID找到的,还是需要额外的查找
router.route('/switchuser')
.post(function (req, res) {
mongoose.model('Users').findById(req.body.idOrName, function (err, user) {
if (err) {
sendErrorResponse(err);
return;
}
if (user) {
loginAs(user, req, res);
return
}
mongoose.model('Users').findOne({ username: req.body.idOrName }, function (err, user) {
if (err) {
sendErrorResponse(err, req, res);
return;
}
if (!user) {
sendNotFoundResponse(req, res);
return;
}
loginAs(user, req, res);
});
});
});
function loginAs(user, req, res) {
req.login(user, function (err) {
if (err) {
res.status(404);
res.send("There was a problem switching the user: " + err);
}
else {
res.format({
html: function () {
res.redirect("/");
}
});
}
})
}
function sendErrorResponse(err, req, res) {
res.status(500);
res.send("Failed to switch user " + err);
}
function sendNotFoundResponse(req, res) {
res.status(404);
res.send("Could not find user");
}
现在,根据您使用的Mongoose JS的版本,Promises的有限版本可能是。您的代码可以像这样进一步清理
router.route('/switchuser')
.post(function (req, res) {
mongoose.model('Users').findById(req.body.idOrName)
.then(function (user) {
// If the user was found, return it down the chain
if (user) {
return user;
}
// If the user was not found, return the promise for the next query
return mongoose.model('Users').findOne({ username: req.body.idOrName });
})
.then(function(user) {
if (!user) {
sendNotFoundResponse(req, res);
return;
}
loginAs(user, req, res);
})
.catch(function(err) {
sendErrorResponse(err, req, res);
});
});
});
function loginAs(user, req, res) {
req.login(user, function (err) {
if (err) {
res.status(404);
res.send("There was a problem switching the user: " + err);
}
else {
res.format({
html: function () {
res.redirect("/");
}
});
}
})
}
function sendErrorResponse(err, req, res) {
res.status(500);
res.send("Failed to switch user " + err);
}
function sendNotFoundResponse(req, res) {
res.status(404);
res.send("Could not find user");
}
您会注意到,通过承诺,您可以在一个
catch
中将所有错误集中在底部。结果更清晰,重复代码和方法调用更少。您可能需要执行exec
以访问catch
方法。只要阅读Mongoose文档就可以了。if语句在req.login
之后没有出现。你的意思是说,req.login
没有等待mongoose.model('Users').findOne(…)
?使用回调模式,“等待”某件事情的唯一方法是在回调完成时调用回调内部的代码。是的,没错。我就是这个意思!有人关闭了此项(不确定为什么关闭此项。您正在经历回调地狱。这可以通过回调解决(正确完成时)但是你可能会考虑承诺或者异步等待,它会清理代码。bit@deceze如果你要在评论中回答,为什么要关闭这个问题?谢谢你的帮助!它工作得很好,但我必须删除第一个if子句“if(err)”,否则它就不工作了。