Как использовать экземпляр express .Router для обработки ошибок - PullRequest
2 голосов
/ 20 января 2020

Согласно документации , любую функцию промежуточного программного обеспечения nodejs express можно заменить экземплярами приложения или маршрутизатора:

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

Это общая обработка ошибок c, которую я использую:

express()
    .use('/test', new TestRouter())
    .use((err, req, res, next) => {
        console.error(err.stack);
        res.status(500).send(err.message);
    })
    .listen(PORT);

Я попытался заменить обработку ошибок на Маршрутизатор обработки ошибок, но теперь обратный вызов никогда не выполняется, и express использует обработку ошибок по умолчанию.

const handler = new express.Router();
handler.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send(err.message);
});

express()
    .use('/test', new TestRouter())
    .use(handler)
    .listen(PORT);

Почему это не работает должным образом и как я могу решить эту проблему?

1 Ответ

3 голосов
/ 20 января 2020

Обработчики ошибок должны быть настроены как последние вызовы use, в соответствии с документами

Вы определяете промежуточное ПО обработки ошибок последним, после другого app.use () и маршрутизирует вызовы;

Я бы сказал, что «маршруты» также включают маршрутизаторы, поэтому то, что вы пытаетесь сделать, не похоже на то, что оно поддерживается.


Просто копать Более того, я считаю, что проблема заключается в том, что маршрутизаторы имеют отдельные стеки слоев. Express за кулисами фактически просто Router (мы видим здесь , где это настроено, а затем дальше, где промежуточное ПО делегировано на маршрутизаторе). Внутренне функции промежуточного программного обеспечения представлены в виде «слоев» (как видно здесь ), и, глядя на конструктор , мы можем видеть, что маршрутизаторы имеют свой собственный стек.

Итак, рассмотрим следующий пример:

express()
  .use(new RouterA())
  .use(new RouterB())
  .use((err, req, res, next) => {
    ...
  })
  .listen(PORT);

Который, глядя на источник, можно рассматривать как:

express()
  .use((req, res, next) => {
    router.handle(req, res, next);
  })
  .use((req, res, next) => {
    router.handle(req, res, next);
  })
  .use((err, req, res, next) => {
    ...
  });

Поэтому, если в RouterA выдается ошибка, маршрутизатор будет во-первых, проверьте свой собственный промежуточный стек на наличие соответствующего уровня ошибок (то есть функции (err, req, res, next)) и выполните его, затем он достигнет уровня приложения и выполнит то же действие.

Итак, приведя свой пример, если Вы рассматриваете переведенный код, это объясняет, почему он не перехватит ваш обработчик ошибок во втором маршрутизаторе - подпись маршрутизатора не совпадает с сигнатурой обработчика ошибок, поэтому он будет пропущен.

...