在node.js express项目中,我想为管理员用户实现切换到用户功能。管理员可以在框中输入用户名或用户ID。下面是处理此请求的代码。问题是,如果第一个数据库调用失败,则在继续登录代码之前,我需要用另一种查询重复该操作。如何在调用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("/");
}
});
}
})
});
});
答案 0 :(得分:0)
您正在经历回调地狱。当通过ID找不到用户时,您将启动第二个回调。问题是您的登录名因为方法在第二个回调之外执行,这意味着它不等待响应。回调地狱会迅速导致大量重复代码。一种解决方案是将您的通用代码提取到函数中。以下是如何执行此操作的一个示例。请注意,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的受限版本可能为available already。您的代码可以像这样进一步清理。
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文档,就可以了。