Как правильно обрабатывать отказ от обещаний в экспрессе - PullRequest
0 голосов
/ 03 апреля 2019

У меня есть следующий экспресс-контроллер

class ThingsController {

  static async index(req, res, next) {
    try {
      const things = await Thing.all();
      res.json(things);
    } catch(err) {
      next(err);
    }  
  }
}

и маршрутизатор

router.route('/things').get(ThingsController.index)

В моем приложении я планирую иметь несколько контроллеров, которые используют обещания для рендеринга результата

Я не хочу повторять блок try / catch каждый раз

Моим первым решением было извлечь эту логику в функцию отклонения обещания дескриптора:

const handlePromiseRejection = (handler) =>

  async (req, res, next) => {
    try{
      await handler(req, res, next);
    } catch(err) {
      next(err);
    };
  };

и теперь мы можем удалить try / catchзаблокировать файл ThingsController.index и изменить маршрутизатор следующим образом:

router.route('/things')
  .get(handlePromiseRejection(ThingsController.index))

Но добавление handlePromiseRejection на каждом маршруте может быть утомительной задачей, и я хотел бы найти более умное решение.

У вас есть идеи?

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

Обычный способ обработки ошибок с async/await в маршрутах - перехватывать ошибки и передавать их обработчику ошибок catch all:

app.use(async (req, res) => {
  try {
    const user = await someAction();
  } catch (err) {
    // pass to error handler
    next(err)
  }
});

app.use((err, req, res, next) => {
  // handle error here
  console.error(err);
});

С пакетом express-async-errors вы можете просто throw (или не беспокоиться о error, выбрасываемом из какой-либо функции). Из документов: Instead of patching all methods on an express Router, it wraps the Layer#handle property in one place, leaving all the rest of the express guts intact.

Простое использование:

require('express-async-errors'); // just require!
app.use(async (req, res) => {
  const user = await User.findByToken(req.get('authorization')); // could possibly throw error, implicitly does catch and next(err) for you

  // throw some error and let it be implicitly handled !!
  if (!user) throw Error("access denied");
});

app.use((err, req, res, next) => {
  // handle error
  console.error(err);
});
0 голосов
/ 04 апреля 2019

Итак, вот как вы справляетесь с отказом от обещаний, если вы действительно хотите обрабатывать каждый маршрут.

Вот его версия с одним вкладышем ES6.

код

const handlePromiseRejection = (handler) => (req, res, next) => handler(req, res, next).catch(next)

Хотя, как вы и просили, самый простой способ - прослушать unhandledRejection процесса, используя ваш index.js или app.js

process.on("unhandledRejection", (error, promise) => {
  console.log("Unhandled Rejection at:", promise, "reason:", reason);
  // Application specific logging, throwing an error, or other logic here
});

С Node.js

...