Почему я не могу позвонить `next` после запуска маршрута в экспрессе? - PullRequest
1 голос
/ 21 мая 2019

У меня есть простой маршрут, подобный этому:

// This is just a health check
const endpoint = (req, res, next) => {
  res.json({
    status: 'ok',
  });
  next();
};

router.get('/', endpoint);

Я получаю Error: Can't set headers after they are sent. от экспресса.Это даже если у меня нет другого возможного промежуточного программного обеспечения для запуска в следующий раз, или если мое next промежуточное программное обеспечение буквально ничего не делает и является пустой функцией.

Что мне не хватает в работе промежуточного программного обеспечения и next работы?

Ответы [ 3 ]

0 голосов
/ 21 мая 2019

Если вам нужно сделать что-то еще в этой конкретной конечной точке, правильным способом будет сделать это перед отправкой ответа.Так работает архитектура экспресса.

Если вы хотите применить одну и ту же логику к каждой конечной точке (похоже, так как вы хотите проверить req.path, req.params и / или req.route)Вы можете использовать промежуточное программное обеспечение для прослушивания события finish express:

router.use((req, res, next) => {
  res.on('finish', function() {
    // extra logic here after sending response
  });
  next();
});

const endpoint = (req, res, next) => {
  res.json({
    status: 'ok',
  });
};

router.get('/', endpoint);
0 голосов
/ 22 мая 2019

Может быть несколько проблем:

В конце у вас есть обработчик 404 (мы все так и делаем) и просто упустили из виду.Например:

app.get('/path', (req, res, next) => {
  res.json({ greet: "Welcome!" })
  next() // <-- calling next middleware
})

// set up a 404 handler at the end
app.use((req, res) => {
  res.status(404).send('Opps! Not Found');
})

Это может привести к ошибке Error: Can't set headers after they are sent. Поскольку ваш обработчик 404 отправляет ответ.

Или Вы наткнулись на Неизвестная функция (или, прямо скажем, один из ваших маршрутов не работает должным образом, возможно, ошибка проектирования).Рассмотрим следующий маршрут:

app.get('/path/:id', (req, res, next) => {
  res.json({ message: "Welcome!" });
  next() // <-- calling next middleware
})

app.get('/path/test', (req, res, next) => {
  res.json({ message: "Welcome!" });
})

Вызов next на маршруте /path/:id может привести к ошибке, если ваш путь запроса /path/test (Это в целом предполагает лучшую реализацию маршрутизации)

Простой способ понять middleware и next связан с тем, как работает switch оператор:

function test(x) {
  switch (x) {
    case 'Oranges':
      console.log('Orange juice');
      break;
    case 'Mangoes': // fall through
    case 'Papayas':
      console.log('Pickles');
      break;
    case 'Banana':
      console.log('Milkshake');
      // forgot the break
    case 'Apple':
      console.log('Apple Pie')
      break;
    default:
      console.log('Sorry, no ' + x + '.');
  }
}

test('Banana')

Вызов next похож на fall through оператора switch, также выполните следующий случай.

Поэтому, когда вы вызываете nextна одном маршруте, и request продолжает совпадать с другим route (непреднамеренное совпадение), когда вы отправляете ответ, вы обнаруживаете, что бьете по лицу с ошибкой.

0 голосов
/ 21 мая 2019

Я думаю, что вы ответили на него в своем собственном вопросе: вы не можете ничего сделать с ответом после того, как он уже был отправлен.И если вы думаете об этом, этот вид имеет смысл.Если next используется для изменения запроса каким-либо образом, почему он все еще "работает", как будто он "работает" после того, как запрос уже был отправлен?

Согласно Экспресс документам , вот как они используют next в запросе get:

app.get('/example/b', function (req, res, next) {
  console.log('the response will be sent by the next function ...')
  next()
}, function (req, res) {
  res.send('Hello from B!')
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...