Отслеживание цепочки middleware

В библиотеке Page.js middleware представляет собой функцию, которая обрабатывает событие навигации перед окончательной загрузкой контента или рендером страницы. Каждая функция middleware получает объект context и функцию next, через которую управление передаётся следующей функции в цепочке. Структура типичного middleware выглядит так:

function middleware(ctx, next) {
  // логика обработки
  next(); // передача управления следующему middleware
}
  • ctx — объект контекста маршрута. Содержит информацию о текущем маршруте: путь, параметры, query-параметры и состояние.
  • next — функция для передачи управления следующему middleware или финальному обработчику.

Middleware можно использовать для:

  • Проверки прав доступа;
  • Подгрузки данных перед отображением страницы;
  • Управления состоянием приложения;
  • Логирования или аналитики.

Регистрация цепочки middleware

Page.js позволяет регистрировать middleware как глобально, так и на уровне конкретного маршрута. Глобальные middleware выполняются для всех маршрутов, а локальные — только для указанного.

// Глобальные middleware
page(middleware1);
page(middleware2);

// Локальные middleware для маршрута /dashboard
page('/dashboard', authMiddleware, dataLoader, dashboardView);

Важно: порядок регистрации имеет критическое значение. Middleware выполняются строго в том порядке, в котором они зарегистрированы.

Передача управления и асинхронные операции

Middleware может содержать асинхронные операции. Важно корректно использовать next, чтобы не блокировать цепочку:

function fetchDataMiddleware(ctx, next) {
  fetch(`/api/data${ctx.path}`)
    .then(response => response.json())
    .then(data => {
      ctx.data = data;
      next();
    })
    .catch(err => {
      console.error(err);
      page.redirect('/error');
    });
}

Если next не вызывается, цепочка middleware прерывается, и последующие функции не выполняются. Это позволяет реализовать условия остановки, например, при отсутствии прав доступа.

Примеры управления цепочкой middleware

  1. Условное выполнение следующего middleware
function authMiddleware(ctx, next) {
  if (ctx.user.isAuthenticated) {
    next();
  } else {
    page.redirect('/login');
  }
}
  1. Добавление состояния в контекст
function stateMiddleware(ctx, next) {
  ctx.state = {
    timestamp: Date.now(),
    pageTitle: 'Demo'
  };
  next();
}
  1. Обработка ошибок в цепочке
function errorHandler(ctx, next) {
  try {
    next();
  } catch (err) {
    console.error('Ошибка в middleware:', err);
    page.redirect('/error');
  }
}

Особенности работы с параметрами маршрута

Middleware имеет доступ к параметрам маршрута через объект ctx.params. Это позволяет динамически подгружать данные или изменять поведение приложения:

page('/user/:id', userMiddleware, userView);

function userMiddleware(ctx, next) {
  const userId = ctx.params.id;
  fetch(`/api/users/${userId}`)
    .then(res => res.json())
    .then(user => {
      ctx.user = user;
      next();
    });
}

Использование цепочки middleware для структурирования приложения

Цепочка middleware позволяет разделять ответственность и писать модульный код:

  • Аутентификация — отдельный middleware;
  • Загрузка данных — отдельный middleware;
  • Рендеринг представления — финальная функция.

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

page(
  '/dashboard',
  authMiddleware,
  fetchDashboardData,
  injectUIState,
  renderDashboard
);

Паттерны сложных цепочек

  1. Комбинированные middleware Можно объединять несколько middleware в один массив и использовать его для маршрутов с одинаковой логикой:
const dashboardMiddleware = [authMiddleware, fetchDashboardData, injectUIState];
page('/dashboard', ...dashboardMiddleware, renderDashboard);
page('/settings', ...dashboardMiddleware, renderSettings);
  1. Каскадная обработка с разветвлениями Цепочка может динамически изменять дальнейший путь выполнения:
function conditionalMiddleware(ctx, next) {
  if (ctx.user.isAdmin) {
    page('/admin');
  } else {
    next();
  }
}

Инструменты для отладки цепочек

Для контроля выполнения middleware можно использовать логирование контекста:

function logger(ctx, next) {
  console.log('Путь:', ctx.path);
  console.log('Параметры:', ctx.params);
  next();
}

Также полезно визуализировать порядок вызова middleware через последовательные консольные сообщения или специальные флаги в контексте.

Рекомендации по организации middleware

  • Держать middleware короткими и специализированными.
  • Всегда вызывать next(), если не требуется прерывать цепочку.
  • Использовать глобальные middleware для повторяющихся операций (логирование, проверка сессии).
  • Локальные middleware использовать для маршрутов с уникальной логикой.
  • Обрабатывать ошибки и асинхронные операции аккуратно, чтобы не блокировать цепочку.

Эффективное использование цепочек middleware в Page.js позволяет строить модульные, расширяемые и легко поддерживаемые SPA-приложения, где каждая логическая операция изолирована и легко тестируема.