Обработка ошибок
Чтобы один кривой запрос не уронил весь сервер — учимся ловить и возвращать ошибки.
Почему это критично
Сервер работает долго и обслуживает многих. Если ошибка в одном запросе не поймана, она может уронить весь процесс — и все клиенты получат отказ. Поэтому ошибки нужно ловить и аккуратно превращать в HTTP-ответы.
Валидация входных данных
Самый частый источник ошибок — некорректный ввод. Проверяйте данные ДО работы с ними и возвращайте 400 Bad Request с понятным сообщением:
app.post("/tasks", (req, res) => {
const { title } = req.body;
if (!title || typeof title !== "string") {
return res.status(400).json({ error: "Поле title обязательно" });
}
// ... создаём задачу
res.status(201).json({ title });
});
Логика проверки — чистый JS, её легко протестировать:
function validateTask(body) {
const errors = [];
if (!body.title) errors.push("title обязателен");
if (body.title && body.title.length > 100) errors.push("title слишком длинный");
if (body.priority && ![1, 2, 3].includes(body.priority)) errors.push("priority вне 1..3");
return errors;
}
console.log(validateTask({ title: "Помыть посуду", priority: 2 }));
console.log(validateTask({ priority: 5 }));
Вывод:
[] [ 'title обязателен', 'priority вне 1..3' ]
try/catch в async-маршрутах
Когда внутри маршрута есть await (запрос к БД, чтение файла), оборачивайте его в try/catch, чтобы поймать сбой и ответить ошибкой, а не «уронить» запрос:
app.get("/tasks/:id", async (req, res) => {
try {
const task = await db.findTask(req.params.id);
if (!task) return res.status(404).json({ error: "Не найдено" });
res.json(task);
} catch (err) {
res.status(500).json({ error: "Внутренняя ошибка сервера" });
}
});
Error-handling middleware
В Express есть особый middleware для ошибок — у него четыре аргумента: (err, req, res, next). Express узнаёт его по числу аргументов и направляет туда все ошибки. Подключают его в самом конце:
// обычные маршруты выше...
// централизованный обработчик ошибок — в самом конце
app.use((err, req, res, next) => {
console.error(err.message);
res.status(500).json({ error: "Что-то пошло не так" });
});
Сюда попадут ошибки, переданные через next(err). Это позволяет не повторять обработку в каждом маршруте, а собрать её в одном месте.
Подходящие статус-коды
| Код | Когда |
| 400 | неверные данные от клиента |
| 401 / 403 | не авторизован / нет прав |
| 404 | ресурс не найден |
| 500 | ошибка на сервере |
Правило: 4xx — виноват клиент (неверный запрос), 5xx — виноват сервер.
Итог
- Валидируйте вход и возвращайте
400с понятным сообщением. - Оборачивайте
awaitв маршрутах вtry/catch. - Error-middleware с 4 аргументами
(err, req, res, next)ставят в конце. - 4xx — ошибка клиента, 5xx — ошибка сервера.