Пользовательские страницы ошибок

Universal Router предоставляет гибкий способ обработки маршрутов и позволяет создавать кастомные страницы ошибок, которые отображаются при некорректных URL или внутренних ошибках маршрутизации. В основе этого лежит механизм обработки исключений, который позволяет перехватывать ошибки и возвращать кастомизированный контент пользователю.


Типы ошибок и их обработка

В Universal Router можно выделить несколько основных сценариев ошибок:

  1. Маршрут не найден (404) Если URL не совпадает ни с одним зарегистрированным маршрутом, библиотека генерирует исключение. Обычно это объект Error с сообщением Route not found.

  2. Ошибка в обработчике маршрута (500) Возникает, если внутри функции action маршрута происходит исключение, например при ошибке работы с данными или неверной логике.

  3. Пользовательские ошибки Любые ошибки, созданные вручную внутри маршрута через 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.
  • Universal Router не выполняет фактический переход по URL; это делается на стороне приложения.

Использование асинхронных страниц ошибок

Функции 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 'Неизвестная ошибка';
    }
  }
];

Преимущества:

  • Поддержка динамического контента.
  • Возможность интеграции с внешними CMS или шаблонизаторами.

Стратегия комбинированной обработки

В крупных приложениях удобно использовать двухуровневую систему обработки ошибок:

  1. Локальные обработчики маршрутов — для специфических ошибок отдельных страниц.
  2. Глобальный errorHandler — для всех остальных непредвиденных ошибок.

Это позволяет создавать гибкую архитектуру: пользователь получает информативные сообщения в рамках контекста страницы, а приложение гарантированно обрабатывает неожиданные сбои.


Рекомендации по организации страниц ошибок

  • Создавать отдельные компоненты или шаблоны для каждой категории ошибки (404, 403, 500).
  • Использовать async функции для загрузки данных или шаблонов динамически.
  • В локальном errorHandler логировать ошибки для аналитики, но не показывать пользователю технические детали.
  • Сохранять консистентный стиль отображения ошибок во всем приложении.

Таким образом, Universal Router предоставляет мощный и гибкий механизм для создания пользовательских страниц ошибок, позволяя различать типы ошибок, настраивать локальные и глобальные обработчики и интегрировать асинхронные источники данных. Это делает маршрутизацию устойчивой к ошибкам и повышает удобство конечного пользователя.