Express.js: передать асинхронные ошибки - PullRequest
0 голосов
/ 04 июля 2018

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

index.js

const controller = require('./controller.js');

const router = new Router();

router.post('/user', controller.createUser);

module.exports = router;

controller.js

exports.createUser = async (req, res, next) => {
    try {
        // asynchronous calls, etc.
    } catch (e) {
        // pass error to middleware
        next(e);
    }
}

Блоки try/catch повторяются в каждом из моих методов контроллера. Я бы хотел, чтобы обнаруженные ошибки передавались в мое промежуточное программное обеспечение для обработки ошибок. Поэтому кажется непрактичным и повторным передавать ошибки в каждой из моих функций контроллера. Могу ли я сделать рефакторинг?

Что если я оберну метод контроллера в функцию как таковую:

index.js

const controller = require('./controller.js');

const router = new Router();

const handleErrors = (func) => async (req, res, next) => {
  try { await func(req, res, next) }
  catch (e) { return next(e) }
};

router.post('/user', handleErrors(controller.createUser));

module.exports = router;

controller.js

exports.createUser = async (req, res, next) => {
    // asynchronous calls, etc.
    if (a !== b) {
        // errors can be passed to middleware as such
        throw new CustomError(400, 'a is not equal to b');
    }
}

Было бы это подходящим решением? Есть ли у Express какие-либо встроенные способы сделать то же самое? Должен ли я быть осторожен с рефакторингом всего моего приложения таким образом?

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

Было бы это подходящим решением?

Да, выглядит красиво.

Есть ли в Express какие-либо встроенные способы выполнения той же задачи?

Нет, Express был написан до того, как async / await был введен.

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

Я так не думаю. Как бы я написал это:

const handleErrors = (func) => (req, res, next) => func(req, res).then(() => next(), next);
0 голосов
/ 04 июля 2018

Я рекомендую вам эту статью: https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016

Как и в статье, это должно быть промежуточное ПО:

const asyncMiddleware = fn =>
  (req, res, next) => {
    Promise.resolve(fn(req, res, next))
      .catch(next);
  };

Вот так должен выглядеть контроллер:

router.get('/users/:id', asyncMiddleware(async (req, res, next) => {
    /* 
      if there is an error thrown in getUserFromDb, asyncMiddleware
      will pass it to next() and express will handle the error;
    */
    const user = await getUserFromDb({ id: req.params.id })
    res.json(user);
}));

router.post('/users', asyncMiddleware(async (req, res, next) => {
  const user = await makeNewUser(req.body);
  res.json(user)
}))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...