gpt4 book ai didi

javascript - 如何链接条件异步回调?

转载 作者:太空宇宙 更新时间:2023-11-04 01:43:43 26 4
gpt4 key购买 nike

在一个node.jsexpress项目中,我想为管理员用户实现切换到用户的功能。管理员可以在框中输入用户名或用户 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("/");
}
});
}
})
});
});

最佳答案

您正在经历回调 hell 。当通过 ID 找不到用户时,您将启动第二次回调。问题是您的登录方法在第二个回调之外执行,这意味着它不会等待响应。回调 hell 很快就会导致大量重复代码。一种解决方案是将常见的代码提取到函数中。以下是您可以如何执行此操作的一个示例。请注意,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");
}

您会注意到,通过 Promise,您可以将所有错误集中在底部的一个 catch 中。重复代码和方法调用更少,结果更清晰。您可能需要执行 exec 才能访问 catch 方法。只要阅读 Mongoose 文档就可以了。

关于javascript - 如何链接条件异步回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52190273/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com