Skip to main content
Практика завдань

Як обробляти помилки в Express.js?

Обробка Помилок в Express.js

Express має вбудований механізм обробки помилок. Правильна обробка помилок є важливою для уникнення збоїв і повернення змістовних відповідей клієнтам.


Синхронні Помилки

Express автоматично перехоплює помилки, що виникають у синхронних обробниках маршрутів:

js
app.get('/user/:id', (req, res) => { if (isNaN(req.params.id)) { throw new Error('ID must be a number'); // Express catches this } res.json({ id: req.params.id }); });

Асинхронні Помилки

Для асинхронного коду ви повинні використовувати try/catch або передавати помилки в next():

js
// Варіант 1: try/catch + next(err) app.get('/users/:id', async (req, res, next) => { try { const user = await User.findById(req.params.id); if (!user) return res.status(404).json({ error: 'Not found' }); res.json(user); } catch (err) { next(err); // передати в обробник помилок } }); // Варіант 2: обгортка asyncHandler const asyncHandler = fn => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next); app.get('/users/:id', asyncHandler(async (req, res) => { const user = await User.findById(req.params.id); if (!user) return res.status(404).json({ error: 'Not found' }); res.json(user); }));

Express 5 (в даний час у RC) автоматично обробляє асинхронні помилки.


Проміжне ПЗ для Обробки Помилок

Обробник помилок має 4 параметри — Express ідентифікує його за аргументом err:

js
// Повинен бути зареєстрований ОСТАННІМ, після всіх маршрутів app.use((err, req, res, next) => { console.error(err.stack); const status = err.statusCode || err.status || 500; const message = err.message || 'Internal Server Error'; res.status(status).json({ success: false, error: message, // показувати стек тільки в режимі розробки ...(process.env.NODE_ENV === 'development' && { stack: err.stack }) }); });

Користувацькі Класи Помилок

js
class AppError extends Error { constructor(message, statusCode) { super(message); this.statusCode = statusCode; this.isOperational = true; Error.captureStackTrace(this, this.constructor); } } class NotFoundError extends AppError { constructor(resource = 'Resource') { super(`${resource} not found`, 404); } } class ValidationError extends AppError { constructor(message) { super(message, 400); } } class UnauthorizedError extends AppError { constructor() { super('Unauthorized', 401); } } // Використання в маршрутах app.get('/users/:id', asyncHandler(async (req, res) => { const user = await User.findById(req.params.id); if (!user) throw new NotFoundError('User'); res.json(user); }));

Обробник 404

Перехоплюйте непідходящі маршрути — зареєструйте його після всіх маршрутів, але ДО обробника помилок:

js
// Після всіх маршрутів app.use((req, res, next) => { next(new NotFoundError(`Route ${req.method} ${req.path}`)); }); // Обробник помилок (остання) app.use((err, req, res, next) => { res.status(err.statusCode || 500).json({ error: err.message }); });

Повна Налаштування Обробки Помилок

js
const express = require('express'); const app = express(); app.use(express.json()); // Маршрути app.use('/api/users', usersRouter); // 404 — повинен йти після всіх маршрутів app.use((req, res, next) => { res.status(404).json({ error: 'Route not found' }); }); // Глобальний обробник помилок — повинен бути останнім app.use((err, req, res, next) => { const status = err.statusCode || 500; res.status(status).json({ error: err.message, ...(process.env.NODE_ENV !== 'production' && { stack: err.stack }) }); }); app.listen(3000);

Резюме

Реєструйте обробники помилок з 4 параметрами і розміщуйте їх останніми в ланцюзі проміжного ПЗ. Використовуйте next(err) для перенаправлення помилок з асинхронного коду, і створюйте користувацькі класи помилок для перенесення кодів статусу HTTP і контекстних повідомлень.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань