Вы испытываете ад обратного вызова. Когда пользователь не найден по 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 может быть доступной уже . Ваш код может быть очищен еще дальше, вот так.
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, и все будет в порядке.