В Page.js маршрутизация строится на обработчиках
маршрутов, которые вызываются при совпадении URL с заданным путем.
Каждый обработчик получает два параметра: объект контекста
ctx и функцию next. Функция next
служит для передачи управления следующему подходящему обработчику.
Понимание работы next критически важно для организации
цепочек middleware, фильтрации запросов и контроля порядка выполнения
логики маршрутов.
nextФункция next вызывается внутри обработчика маршрута
следующим образом:
page('/profile', function(ctx, next) {
console.log('Первый обработчик');
next(); // Передаём управление следующему обработчику
});
page('/profile', function(ctx) {
console.log('Второй обработчик');
});
В этом примере при переходе на /profile сначала
выполняется первый обработчик, затем, после вызова next(),
управление передаётся второму. Если next не вызывается,
выполнение цепочки маршрутов прекращается, и следующие обработчики не
вызываются.
Ключевые моменты:
next() продолжает выполнение цепочки middleware для
текущего маршрута.next можно вызывать асинхронно, например, после
выполнения промиса.next — стандартный способ остановки
дальнейшей обработки.Page.js поддерживает несколько обработчиков для одного маршрута. Middleware могут фильтровать или модифицировать контекст перед передачей управления:
function authMiddleware(ctx, next) {
if (!ctx.user) {
page.redirect('/login');
} else {
next();
}
}
function logMiddleware(ctx, next) {
console.log(`Пользователь зашёл на ${ctx.path}`);
next();
}
page('/dashboard', authMiddleware, logMiddleware, function(ctx) {
console.log('Основной обработчик страницы');
});
Принципы работы:
next(), цепочка
останавливается.nextnext можно использовать после асинхронных операций, что
позволяет строить цепочки обработки с задержкой:
page('/data', async (ctx, next) => {
ctx.data = await fetchDataFromServer();
next();
});
page('/data', (ctx) => {
console.log('Данные загружены:', ctx.data);
});
Здесь первый обработчик загружает данные и сохраняет их в контексте
ctx. После завершения загрузки вызывается
next(), и второй обработчик получает уже подготовленный
контекст. Это ключевой паттерн при работе с асинхронными данными в
SPA.
nextnext также полезен для вложенных маршрутов. Можно
создавать обработчики, которые срабатывают на общую часть пути, а затем
передавать управление конкретному маршруту:
page('/users', (ctx, next) => {
console.log('Общий обработчик для всех пользователей');
next();
});
page('/users/:id', (ctx) => {
console.log('Пользователь с ID:', ctx.params.id);
});
Переход на /users/42 сначала вызовет общий обработчик, а
затем — конкретный. Такой подход позволяет централизованно обрабатывать
авторизацию, логирование или настройку контекста для группы
маршрутов.
Функция next может вызываться условно, что позволяет
реализовать гибкие цепочки обработки:
page('/shop', (ctx, next) => {
if (ctx.query.showPromo) {
console.log('Показ промо');
next();
}
});
page('/shop', (ctx) => {
console.log('Основной контент магазина');
});
Если условие ctx.query.showPromo истинно, управление
передается следующему обработчику, иначе — цепочка останавливается.
next с редиректами и завершением маршрутаРедиректы и остановка маршрута взаимодействуют с next
особым образом:
page('/admin', (ctx, next) => {
if (!ctx.user.isAdmin) {
page.redirect('/login'); // Не вызывает next, цепочка прекращается
} else {
next(); // Админ, продолжаем
}
});
page('/admin', (ctx) => {
console.log('Админская панель');
});
Редирект автоматически прерывает текущую цепочку. Вызов
next() после редиректа не имеет смысла и может вызвать
нежелательное поведение.
next(), если обработчик не должен
завершать маршрут.next() для асинхронной подготовки данных
перед основным обработчиком.next с редиректами для
гибкого управления доступом к страницам.next.Эта концепция передачи управления через next является
фундаментальной для построения сложных SPA с Page.js, обеспечивая
модульность, читаемость кода и гибкую маршрутизацию.