В Universal Router middleware выполняют ключевую роль в обработке запросов и маршрутов, обеспечивая гибкость и возможность расширения логики маршрутизации. Одной из критических задач при работе с middleware является правильная обработка ошибок, чтобы приложение могло корректно реагировать на неожиданные ситуации без полной остановки работы.
Middleware в Universal Router представляют собой функции вида:
async function middleware(context, next) {
// код middleware
await next();
}
Где:
context — объект, содержащий информацию о текущем
маршруте, параметрах, состоянии приложения.next — функция, вызывающая следующий middleware или
конечный обработчик маршрута.Для обработки ошибок используется конструкция try/catch:
async function errorHandlingMiddleware(context, next) {
try {
await next();
} catch (err) {
console.error('Произошла ошибка:', err);
context.error = err;
// Можно перенаправить на специальный маршрут ошибки
return { redirect: '/error' };
}
}
Ключевые моменты:
await next() оборачивается в try/catch,
чтобы перехватить любые ошибки в последующих middleware или в конечных
маршрутах.context.error позволяет другим частям приложения
анализировать причины сбоя без необходимости заново выбрасывать
исключение.Все middleware Universal Router поддерживают асинхронные операции.
Исключения, возникшие внутри async/await, автоматически
превращаются в промис-ошибку, которую можно перехватить:
async function asyncMiddleware(context, next) {
try {
const data = await fetchData(context.params.id); // может выбросить ошибку
context.data = data;
await next();
} catch (err) {
console.warn('Ошибка при загрузке данных:', err.message);
context.error = err;
return { component: 'ErrorComponent' };
}
}
Особое внимание стоит уделять асинхронным функциям внутри middleware, так как необработанная ошибка может остановить весь процесс маршрутизации.
Universal Router позволяет создавать маршруты для обработки ошибок, чтобы разделить логическую обработку ошибок и отображение ошибок пользователю:
const routes = [
{
path: '/error',
action: () => ({ component: 'ErrorPage' })
},
{
path: '/user/:id',
action: async ({ params }) => {
if (!params.id) throw new Error('ID пользователя отсутствует');
return { component: 'UserPage', userId: params.id };
}
}
];
Middleware, перехватывающий ошибки, может перенаправлять на
/error или возвращать специализированный компонент для
отображения ошибки.
Для крупных приложений рекомендуется внедрять глобальный middleware, который оборачивает все маршруты:
const router = new UniversalRouter(routes, {
context: {},
resolveRoute(context, params) {
return context.route.action(context, params);
}
});
router.use(async (context, next) => {
try {
await next();
} catch (err) {
console.error('Глобальная ошибка:', err);
context.error = err;
return { component: 'GlobalErrorComponent' };
}
});
Такой подход гарантирует, что любая ошибка в маршрутах или других middleware будет обработана единообразно, а приложение не завершится аварийно.
Помимо перехвата, middleware может выполнять логирование, отправку ошибок на сервер мониторинга или генерацию пользовательских сообщений:
async function loggingMiddleware(context, next) {
try {
await next();
} catch (err) {
sendToMonitoringService(err); // внешняя система логирования
throw err; // повторная генерация ошибки для следующего уровня
}
}
Особенность: повторная генерация ошибки
(throw err) позволяет передать управление другому
middleware, который может уже корректно отобразить ошибку
пользователю.
Правильная организация middleware и системная обработка ошибок в Universal Router повышают устойчивость приложения и позволяют поддерживать сложные маршруты без потери контроля над исключениями.