Ваш код показывает пару проблем:
Вы пытаетесь отправить двойной ответ. Сначала вы бросаете res.status(404).json(...)
. Затем вы перехватываете это исключение и снова делаете res.status(404).json(e)
. Это не правильно. Если вы собираетесь отправить ответ, то просто вернитесь, не бросайте. Или просто сгенерируйте исключение, не отправляя ответ, и отправьте фактический ответ об ошибке из обработчика перехвата.
Кроме того, throw res.status(404).json({error: 'No match'});
отправляет ответ, а затем выдает все, что .json()
возвращает, что это, вероятно, не то, что вы хотите. Это не будет какой-либо объект ошибки.
Я предпочитаю централизовать места, в которые я отправляю ответ об ошибке, в одно место в обработчике запросов. Это удерживает вас от попыток отправить несколько ответов и просто облегчает понимание потока обработчика запросов (на мой взгляд).
Для этого я просто throw
пользовательская ошибка, которая может иметь пользовательское сообщение / статус, связанный с ним, а затем перехватывать все возможные ошибки в одном месте. Вот один из способов сделать это. Класс myError
может использоваться везде в вашем проекте, но не может указывать c только для одного маршрута. Идея состоит в том, что часто, когда вы throw
, вы знаете в этом контексте, какой вы хотите статус и сообщение, чтобы вы устанавливали это в пользовательском объекте Error и затем могли использовать эту информацию в перехвате. Затем улов должен определить, есть ли у вас пользовательская ошибка или просто обычная ошибка. Во-первых, у меня есть подкласс Error многократного использования, который позволяет мне выдавать не только сообщение, но и значение состояния.
// reusable error class that contains a status in addition to the message
class MyError extends Error {
// this static method saves having to compare if it's a custom error object or not
// every time we use this
static sendError(res, e, status = 500) {
if (e instanceof MyError) {
e.sendError(res);
} else {
res.sendStatus(status);
}
}
constructor(msg, status = 500) {
// allow calling with or without new
if (!(this instanceof MyError)) {
return new MyError(msg, status);
}
super(msg);
this.status = status;
}
sendError(res) {
res.status(this.status).send(this.message);
}
}
И затем вот как вы используете это в своем коде и централизует отправку статус ошибки.
app.post('/', async (req, res) => {
try {
const { email } = req.body.email; // destructuring
const usuarioEncontrado = await Usuario.findOne({email: email});
// Validate user exist
if (!usuarioEncontrado) { // when not exist return null
throw MyError('El usuario no existe', 404);
}
// validate user pass
if (!bcrypt.compareSync(req.body.password, usuarioEncontrado.password)) {
throw MyError('No Match', 404);
}
const token = jwt.sign( // generate token
{
usuario: usuarioEncontrado
},
SEED,
{
expiresIn: (60 * 60)
}
);
res.status(200).json({ // send response
token: token,
usuario: usuarioEncontrado
});
} catch (e) { // log and send error response
// e may be either MyError or some other system generated Error
console.log(e);
MyError.sendError(res, e);
}
}