← Назад к вопросам

Что такое параметр next в middleware?

1.7 Middle🔥 131 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Параметр next в middleware

Это ключевой концепт для понимания как работает middleware паттерн. Разберём со всех сторон.

Что такое middleware?

Middleware — это функция, которая обрабатывает HTTP запрос, выполняет какие-то действия, и затем передаёт управление следующему middleware или обработчику.

// Базовая структура middleware
function middleware(req, res, next) {
  // 1. Выполняем какое-то действие
  console.log('Запрос получен');
  
  // 2. Вызываем next() для передачи управления дальше
  next();
  
  // 3. Код может выполниться ПОСЛЕ next()
  console.log('Запрос завершён');
}

Понимание параметра next

Параметр next — это функция, которая вызывает следующий middleware в цепочке:

// Цепочка middleware в Express
app.use(middleware1); // middleware 1
app.use(middleware2); // middleware 2
app.use(middleware3); // middleware 3
app.get('/users', handler); // конечный обработчик

// Когда приходит запрос, выполняется:
// middleware1(req, res, next1) {
//   next1(); // -> middleware2
// }
// middleware2(req, res, next2) {
//   next2(); // -> middleware3
// }
// middleware3(req, res, next3) {
//   next3(); // -> handler
// }
// handler(req, res) {
//   res.json(data);
// }

Практические примеры

Пример 1: Логирование

const express = require('express');
const app = express();

// Middleware для логирования
function loggerMiddleware(req, res, next) {
  console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
  next(); // передаём управление дальше
}

app.use(loggerMiddleware);

app.get('/users', (req, res) => {
  res.json({ users: [] });
});

// Вывод:
// [2024-01-15T10:30:00.000Z] GET /users

Пример 2: Аутентификация

function authMiddleware(req, res, next) {
  const token = req.headers.authorization;
  
  if (!token) {
    // Не вызываем next() - прерываем цепочку
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  try {
    const decoded = verifyToken(token);
    req.user = decoded; // добавляем данные пользователя
    next(); // вызываем next если аутентификация успешна
  } catch (error) {
    res.status(401).json({ error: 'Invalid token' });
  }
}

app.use(authMiddleware); // применяем ко всем маршрутам

app.get('/protected', (req, res) => {
  res.json({ user: req.user }); // req.user добавлен middleware
});

Пример 3: Обработка ошибок

function errorHandler(err, req, res, next) {
  // Обработчик ошибок ВСЕГДА имеет 4 параметра!
  console.error('Ошибка:', err);
  
  res.status(err.status || 500).json({
    error: err.message
  });
}

app.get('/data', (req, res, next) => {
  try {
    const data = fetchData();
    res.json(data);
  } catch (error) {
    next(error); // передаём ошибку в обработчик ошибок
  }
});

app.use(errorHandler); // ДОЛЖЕН быть последним!

Порядок выполнения middleware

Это очень важно понимать:

const express = require('express');
const app = express();

// 1. Парсинг JSON
app.use(express.json());

// 2. Логирование
app.use((req, res, next) => {
  console.log('1. Логирование');
  next();
});

// 3. Проверка аутентификации
app.use((req, res, next) => {
  console.log('2. Аутентификация');
  next();
});

// 4. Специальный маршрут
app.get('/users', (req, res, next) => {
  console.log('3. Обработчик /users');
  res.json({ users: [] });
});

// 5. Другой маршрут
app.get('/posts', (req, res) => {
  console.log('4. Обработчик /posts');
  res.json({ posts: [] });
});

// Вывод для GET /users:
// 1. Логирование
// 2. Аутентификация
// 3. Обработчик /users

// Вывод для GET /posts:
// 1. Логирование
// 2. Аутентификация
// 4. Обработчик /posts

Что происходит если НЕ вызвать next()?

Если забыть вызвать next(), управление не передаётся дальше:

app.use((req, res, next) => {
  console.log('Middleware 1');
  // ЗАБЫЛИ вызвать next()!
});

app.get('/test', (req, res) => {
  console.log('Handler'); // НИКОГДА НЕ ВЫПОЛНИТСЯ!
  res.json({ ok: true });
});

// Запрос повисает, так как никто не отправляет ответ!

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

В современном Node.js используются async функции:

const express = require('express');
const app = express();

// Async middleware
app.use(async (req, res, next) => {
  try {
    const user = await fetchUserFromDB(req.userId);
    req.currentUser = user;
    next(); // передаём управление дальше
  } catch (error) {
    next(error); // передаём ошибку в обработчик
  }
});

app.get('/profile', async (req, res, next) => {
  try {
    const profile = await getProfile(req.currentUser.id);
    res.json(profile);
  } catch (error) {
    next(error); // ошибка перехватится errorHandler
  }
});

Правила использования next

// ПРАВИЛО 1: Вызывай next() или отправь ответ
function middleware(req, res, next) {
  if (shouldContinue) {
    next(); // передаём дальше
  } else {
    res.status(400).json({ error: 'Bad request' }); // отправляем ответ
  }
}

// ПРАВИЛО 2: Не вызывай next() дважды
function badMiddleware(req, res, next) {
  next();
  next(); // БЕД! Может привести к проблемам
}

// ПРАВИЛО 3: Отправляй ответ или вызывай next(), но не оба
function middleware(req, res, next) {
  // ПЛОХО:
  res.json({ ok: true });
  next(); // Это странно и может вызвать проблемы
  
  // ХОРОШО:
  if (someCondition) {
    res.json({ ok: true });
  } else {
    next();
  }
}

// ПРАВИЛО 4: Передавай ошибки в next(error)
function middleware(req, res, next) {
  try {
    const data = JSON.parse(req.body);
    next();
  } catch (error) {
    next(error); // передаём ошибку, не просто вызываем
  }
}

Визуализация цепочки

Запрос приходит
    |
    v
[middleware 1] --> next() вызвана?
    |                  |
    |         ДА ->   [middleware 2] --> next() вызвана?
    |                  |                      |
    |                  |           ДА ->   [middleware 3] --> next() вызвана?
    |                  |                      |                      |
    |                  |                      |           ДА ->   [handler]
    |                  |                      |                      |
    |                  |                      |                      v
    |                  |                      |                [отправляем ответ]
    |                  |                      |                      ^
    |                  |                      | НЕТ / ошибка        |
    |                  |                      |                      |
    |                  |                      +-------> [errorHandler]
    |                  |                                      ^
    |                  | НЕТ / ошибка                         |
    |                  +-------> [errorHandler]
    |                                        ^
    | НЕТ / ошибка                          |
    +-------> [errorHandler]

Практический пример: полная цепочка

const express = require('express');
const app = express();

// 1. Парсинг JSON
app.use(express.json());

// 2. Логирование
app.use((req, res, next) => {
  console.log(`Запрос: ${req.method} ${req.url}`);
  next();
});

// 3. Проверка токена
app.use((req, res, next) => {
  const token = req.headers.authorization;
  if (!token && req.url !== '/login') {
    return res.status(401).json({ error: 'No token' });
  }
  next();
});

// 4. Добавление user в request
app.use((req, res, next) => {
  req.user = { id: 1, name: 'John' }; // пример
  next();
});

// 5. Обработчик маршрута
app.get('/users', (req, res) => {
  res.json({ users: [], currentUser: req.user });
});

// 6. Обработчик ошибок
app.use((err, req, res, next) => {
  console.error('Ошибка:', err);
  res.status(500).json({ error: err.message });
});

app.listen(3000);

// Когда приходит GET /users:
// Логирование -> Проверка токена -> Добавление user -> Обработчик

Заключение

Параметр next — это функция, которая передаёт управление следующему middleware. Она критична для управления потоком выполнения в Express приложении. Понимание этого паттерна очень важно для разработки backend приложений.

Что такое параметр next в middleware? | PrepBro