Universal Router предоставляет гибкий механизм для маршрутизации запросов в приложениях на JavaScript, включая возможность обработки ошибок. Ошибки могут возникать на разных уровнях: при разрешении маршрута, при выполнении асинхронных действий или при генерации контента. Для эффективного восстановления после ошибок необходимо понимать архитектуру маршрутизатора и способы интеграции обработчиков ошибок.
Каждый маршрут в Universal Router описывается объектом с ключами
path и action. Функция action
может быть асинхронной и возвращать промис. Если в процессе выполнения
происходит ошибка, промис отклоняется, что позволяет централизованно или
локально обрабатывать исключения.
const router = new UniversalRouter([
{
path: '/user/:id',
action: async ({ params }) => {
if (!params.id) {
throw new Error('ID пользователя не указан');
}
return fetchUserData(params.id);
}
}
]);
В приведенном примере при отсутствии id генерируется
ошибка. Universal Router позволяет перехватывать такие ошибки на уровне
маршрута или глобально.
Для централизованной обработки ошибок используется метод
resolve с блоком catch. Это позволяет
перехватывать все ошибки, возникающие в маршрутах, и возвращать
стандартный ответ или перенаправлять на страницу ошибки.
router.resolve({ pathname: '/user/' })
.then(result => {
console.log('Результат маршрута:', result);
})
.catch(error => {
console.error('Произошла ошибка при маршрутизации:', error);
return renderErrorPage(error);
});
Ключевым моментом является то, что даже при асинхронных ошибках
промис автоматически перейдет в состояние rejected, и
обработка в catch позволит корректно восстановить состояние
приложения.
Иногда требуется обработка ошибок непосредственно в маршруте, чтобы
предоставить специфическую логику восстановления или альтернативный
маршрут. Для этого в action можно использовать блоки
try/catch.
const router = new UniversalRouter([
{
path: '/profile/:id',
action: async ({ params }) => {
try {
const profile = await fetchProfile(params.id);
return profile;
} catch (err) {
console.warn('Ошибка загрузки профиля:', err);
return redirectTo('/error-profile');
}
}
}
]);
В данном примере ошибка загрузки профиля не прерывает работу всего маршрутизатора, а направляет пользователя на альтернативную страницу.
Universal Router поддерживает вложенные маршруты, что позволяет создавать цепочки маршрутизации с собственными обработчиками ошибок. Родительский маршрут может перехватывать ошибки дочерних маршрутов и выполнять централизованное восстановление.
const router = new UniversalRouter([
{
path: '/dashboard',
action: async ({ next }) => {
try {
return await next();
} catch (err) {
console.error('Ошибка на панели:', err);
return renderDashboardFallback();
}
},
children: [
{ path: 'stats', action: () => fetchStats() },
{ path: 'settings', action: () => fetchSettings() }
]
}
]);
Использование next() позволяет обрабатывать ошибки всех
дочерних маршрутов в одном месте, упрощая управление восстановлением
состояния.
Часто необходимо обрабатывать ситуации, когда путь не совпадает ни с
одним маршрутом. Для этого можно использовать маршрут с
path: '(.*)', который будет перехватывать все
неопределенные пути.
const router = new UniversalRouter([
// другие маршруты
{
path: '(.*)',
action: () => renderNotFoundPage()
}
]);
Такой подход позволяет создать универсальный механизм восстановления для любых некорректных запросов.
При работе с асинхронными действиями важно помнить, что промисы могут
быть отклонены в любой момент. Рекомендуется оборачивать критические
вызовы в блоки try/catch или использовать
Promise.catch, чтобы предотвратить падение приложения.
async function fetchUserData(id) {
try {
const response = await fetch(`/api/user/${id}`);
if (!response.ok) throw new Error('Сервер вернул ошибку');
return response.json();
} catch (err) {
console.error('Ошибка при запросе данных пользователя:', err);
throw err;
}
}
Для полноценного восстановления после ошибок важно логировать все исключения и при необходимости уведомлять пользователя или службу мониторинга. Это позволяет выявлять системные проблемы и улучшать стабильность приложения.
router.resolve({ pathname: '/profile/42' })
.catch(error => {
logError(error);
notifyUser('Произошла ошибка при загрузке страницы');
return renderErrorPage(error);
});
catch.next() для
централизованного перехвата ошибок.Эти практики обеспечивают стабильную работу Universal Router и позволяют корректно восстанавливаться после любых ошибок, возникающих на этапе маршрутизации и асинхронной обработки данных.