Специфичные middleware

В библиотеке Navigo middleware позволяют управлять маршрутизацией на более гибком уровне, обрабатывая запросы до того, как они достигнут целевого обработчика маршрута. Middleware — это функции, которые выполняются последовательно и могут модифицировать контекст маршрута, перенаправлять пользователя или блокировать переход. Их применение особенно важно в сложных приложениях с авторизацией, логированием или асинхронной загрузкой данных.


Регистрация middleware

Middleware в Navigo регистрируются с помощью метода use(). Каждая функция получает объект params, содержащий параметры маршрута, и объект next, который запускает выполнение следующего middleware или обработчика маршрута:

const router = new Navigo('/');

router.use((params, next) => {
  console.log('Текущий маршрут:', params);
  next();
});

Особенности:

  • Middleware вызываются в порядке их регистрации.
  • Если middleware не вызовет next(), выполнение маршрута будет остановлено.
  • Можно регистрировать глобальные middleware для всех маршрутов или специфичные для отдельных маршрутов через on().

Контекст middleware

Middleware получает следующие параметры:

  • params — объект с параметрами маршрута, например {id: '123'}.
  • query — объект с параметрами запроса URL, например ?filter=active.
  • next — функция для передачи управления следующему middleware или обработчику.
  • route — объект текущего маршрута с его конфигурацией.

Пример использования параметров запроса:

router.use((params, next, route) => {
  if (route.query && route.query.token) {
    console.log('Токен пользователя:', route.query.token);
  }
  next();
});

Асинхронные middleware

Navigo поддерживает асинхронные операции внутри middleware. Это позволяет загружать данные с сервера перед отображением страницы:

router.use(async (params, next) => {
  try {
    const user = await fetch(`/api/users/${params.id}`).then(res => res.json());
    params.user = user; // передача данных в последующие middleware или обработчик
    next();
  } catch (error) {
    console.error('Ошибка загрузки данных:', error);
  }
});

Ключевой момент: асинхронный middleware не блокирует цепочку, если next() вызван внутри try/catch. Если next() не вызывается, переход на маршрут не произойдет.


Middleware для авторизации

Частая задача — проверка прав пользователя перед отображением маршрута. Middleware может перенаправлять на страницу логина или запрещать доступ:

router.use((params, next, route) => {
  const isAuthenticated = Boolean(localStorage.getItem('authToken'));
  if (!isAuthenticated && route.path !== '/login') {
    router.navigate('/login');
  } else {
    next();
  }
});

Особенности реализации:

  • Проверка выполняется перед обработчиком маршрута.
  • Можно комбинировать несколько middleware для различных уровней доступа.
  • Middleware может модифицировать объект params, чтобы передавать статус авторизации или роль пользователя.

Условные middleware

Middleware может быть активным только для определённых маршрутов или условий. Это удобно для страниц с уникальной логикой или асинхронной загрузкой данных:

router.use((params, next, route) => {
  if (route.path.startsWith('/admin')) {
    const isAdmin = checkUserRole() === 'admin';
    if (!isAdmin) {
      router.navigate('/403');
      return;
    }
  }
  next();
});

Вложенные middleware

Можно создавать цепочки middleware, где каждый элемент управляет своим фрагментом логики:

const logMiddleware = (params, next) => {
  console.log('Маршрут:', params.route);
  next();
};

const authMiddleware = (params, next, route) => {
  if (!params.user) {
    router.navigate('/login');
  } else {
    next();
  }
};

router.use(logMiddleware);
router.use(authMiddleware);

Преимущества вложенных middleware:

  • Повторное использование функций на нескольких маршрутах.
  • Чёткая логика разделения ответственности: логирование, авторизация, проверка данных.
  • Легкость тестирования и отладки.

Обработка ошибок в middleware

Ошибки внутри middleware можно перехватывать и управлять переходом:

router.use(async (params, next) => {
  try {
    await fetchData(params.id);
    next();
  } catch (err) {
    console.error('Ошибка в middleware:', err);
    router.navigate('/error');
  }
});

Рекомендации:

  • Не оставлять необработанные промисы внутри middleware.
  • Использовать try/catch для асинхронных операций.
  • Перенаправление на страницу ошибки улучшает UX и предотвращает зависание приложения.

Заключение по специфичным middleware

Middleware в Navigo — это мощный инструмент для управления маршрутизацией на глубоком уровне. Они позволяют реализовать авторизацию, логирование, асинхронную загрузку данных, условные переходы и обработку ошибок. Правильная структура и порядок регистрации middleware обеспечивает стабильность и предсказуемость навигации в приложении.