Асинхронизация / ожидание в Nodejs + Mongoose - PullRequest
0 голосов
/ 01 октября 2019

Я новичок в Обещаниях и асинхронном / ожидаемом программировании, и я не уверен, что понял все правильно. Я создаю API в Nodejs, с Express, Mongoose и MongoDB. Я видел много учебников о том, как бороться с асинхронностью, но все они о проектах NodeJ, в которых маршрутизация и запрос БД находятся в одном файле. пример:

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

router.get('/users/:id', asyncMiddleware(async (req, res, next) => {
    const something = await getSomethingFromDb({ id: req.params.id })
    res.json(something);
}));

Однако для ясности я отделил маршрутизацию от контроллера, но у меня есть серьезные сомнения, что я сделал это правильно. Вот мой код:

router.js

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

router.get('/something/:id', asyncMiddleware(async (req, res, next) => {
    const answer = await somethingController.findById(req, res, next)
}));

controller.js

exports.findById = async (req, res, next) => {
    const something = await Something.findById(req.params.id).exec();
    res.send(something);
};

Я пыталсяв console.log (), чтобы проверить, что печатается и что, но я понял, что из-за ожидающей части весь этот фрагмент кода будет ожидать завершения запроса. Это хорошо реализовано? Как я могу проверить это?

Версии: NodeJs v10.16.3 Mongoose v5.7.1

Ответы [ 2 ]

4 голосов
/ 01 октября 2019

Во-первых, вам не нужно "asyncMiddleware". Позвольте мне привести полный пример того, как можно разделять маршруты и контроллеры, сохраняя при этом асинхронность контроллера:

Контроллер

exports.findById = async (req, res, next) => {
    try{
       const something = await Something.findById(req.params.id).exec();
       res.send(something);
    }catch(err){
       return res.status(500).send({
        message: err.message
      })
    }   
};

Выследует обернуть вас async вызовами в блок try / catch.

Маршрут

Затем вы просто вызовете свой контроллер на своем маршруте, какитак:

router.get('/:id', Controller.findByID)

и все. Вам не нужен дополнительный вызов async на вашем маршруте.

Если у вас есть промежуточное ПО, и вы хотите добавить свой маршрут, вы можете сделать это следующим образом:

//for single middleware
router.get('/:id',somethingMiddle,Controller.findByID)

//for multiple middleware
router.get('/:id',[somethingMiddle, anotherMiddle],Controller.findByID)

Дайте мне знатьесли это поможет

1 голос
/ 01 октября 2019

Лично я предпочел бы использовать try-catch для своих асинхронных функций, а не промежуточное программное обеспечение. Это может выглядеть примерно так:

module.exports.view = async function(req, res, next) {
  try {
    var something = await Something.findById(req.params.id).orFail();
    res.send(something);
  } catch (err) {
    next(err);
  }
};

Тогда в вашем маршрутизаторе это будет просто:

router.get('/something/:id', somethingController.view);

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

Теперь я не уверен, ожидаете ли вы этого или нет, но вы можете вызвать .orFail() в своем запросе,Таким образом выдается ошибка, если «что-то» с указанным идентификатором не найдено. В противном случае переменная something будет нулевой. Но это полностью зависит от того, как вы хотите, чтобы ваш API функционировал.

Кроме того, когда вы определяете функцию async, в основном говорится, что функция возвращает Promise. Оператор await в основном говорит программе приостановить функцию, пока обещание не будет выполнено. В этом примере await будет ждать, пока база данных вернет результат, прежде чем продолжить действие контроллера. Express волшебным образом справится с ожиданием ваших async методов маршрутов и промежуточного программного обеспечения.

...