Universal Router предоставляет гибкий способ обработки маршрутов и позволяет создавать кастомные страницы ошибок, которые отображаются при некорректных URL или внутренних ошибках маршрутизации. В основе этого лежит механизм обработки исключений, который позволяет перехватывать ошибки и возвращать кастомизированный контент пользователю.
В Universal Router можно выделить несколько основных сценариев ошибок:
Маршрут не найден (404) Если URL не совпадает ни
с одним зарегистрированным маршрутом, библиотека генерирует исключение.
Обычно это объект Error с сообщением
Route not found.
Ошибка в обработчике маршрута (500) Возникает,
если внутри функции action маршрута происходит исключение,
например при ошибке работы с данными или неверной логике.
Пользовательские ошибки Любые ошибки, созданные
вручную внутри маршрута через
throw new Error('Описание ошибки'), могут быть обработаны
единообразно.
Ключевой элемент — добавление блока catch или
использование конструкции try/catch внутри функции
маршрута. Пример стандартного подхода:
import UniversalRouter from 'universal-router';
const routes = [
{
path: '/',
action: () => 'Главная страница'
},
{
path: '/about',
action: () => 'О нас'
}
];
const router = new UniversalRouter(routes, {
errorHandler: (error, context) => {
if (error.message === 'Route not found') {
return 'Страница не найдена (404)';
}
return 'Произошла внутренняя ошибка (500)';
}
});
// Пример использования
router.resolve({ pathname: '/unknown' })
.then(console.log)
.catch(console.error);
Пояснение:
errorHandler принимает два параметра: объект ошибки и
контекст маршрута.errorHandler можно возвращать строку, HTML,
объект с данными или даже перенаправление на другой маршрут.Universal Router позволяет настраивать обработку ошибок не только глобально, но и для конкретного маршрута:
const routes = [
{
path: '/profile/:id',
action: async ({ params }) => {
const user = await fetchUser(params.id);
if (!user) throw new Error('UserNotFound');
return renderUser(user);
},
errorHandler: (error) => {
if (error.message === 'UserNotFound') {
return 'Пользователь не найден';
}
return 'Ошибка загрузки профиля';
}
}
];
Особенности локального
errorHandler:
Для улучшения UX можно перенаправлять пользователя на отдельный маршрут при возникновении ошибки:
const routes = [
{ path: '/login', action: () => 'Страница входа' },
{
path: '/dashboard',
action: () => { throw new Error('Unauthorized'); },
errorHandler: () => ({ redirect: '/login' })
}
];
const router = new UniversalRouter(routes);
router.resolve({ pathname: '/dashboard' })
.then(result => {
if (result.redirect) {
console.log(`Перенаправление на ${result.redirect}`);
}
});
Важно:
redirect.Функции action и errorHandler могут быть
асинхронными, что позволяет подгружать шаблоны ошибок с сервера или
динамически формировать контент:
const routes = [
{
path: '/reports/:id',
action: async ({ params }) => {
const report = await fetchReport(params.id);
if (!report) throw new Error('ReportNotFound');
return report.content;
},
errorHandler: async (error) => {
if (error.message === 'ReportNotFound') {
const template = await fetch('/templates/404.html').then(r => r.text());
return template;
}
return 'Неизвестная ошибка';
}
}
];
Преимущества:
В крупных приложениях удобно использовать двухуровневую систему обработки ошибок:
errorHandler — для всех
остальных непредвиденных ошибок.Это позволяет создавать гибкую архитектуру: пользователь получает информативные сообщения в рамках контекста страницы, а приложение гарантированно обрабатывает неожиданные сбои.
async функции для загрузки данных или
шаблонов динамически.errorHandler логировать ошибки для
аналитики, но не показывать пользователю технические детали.Таким образом, Universal Router предоставляет мощный и гибкий механизм для создания пользовательских страниц ошибок, позволяя различать типы ошибок, настраивать локальные и глобальные обработчики и интегрировать асинхронные источники данных. Это делает маршрутизацию устойчивой к ошибкам и повышает удобство конечного пользователя.