Шаблон проектирования результатов обработки запросов NodeJS позволяет избежать вложенных операторов - PullRequest
0 голосов
/ 29 мая 2019

Я пишу приложение в NodeJS10 и Mongoose5.Я пишу пользовательскую функцию нумерации на стороне сервера.Я хочу запустить нумерацию страниц в контроллере для разделения проблем и возможности повторного использования.

У меня есть запрос, чтобы получить данные и вернуть их в обработчик ответа then ().Затем я вызываю пользовательскую функцию разбиения на страницы внутри обработчика then ().Это работает, но меня беспокоят "вложенные" шаблоны then / catch.Я думаю, что это может быть грязно, особенно если требуется дополнительная обработка данных перед возвратом ответа.

Вот «вложенная» структура.Как я могу улучшить это, чтобы оно больше не было вложенным и более читабельным, при этом все еще перехватывая все возможные ошибки и возвращая правильный ответ?Обратите внимание, что это работает просто отлично, просто шаблон проектирования запутан, и я хочу по возможности избегать «вложенных» операторов then ().

router.get('/:id', (req, res, next) => {
  const origin = 'routes/items.js GET /:id';

  const id = req.params.id;

  items.find({
    _id: id
  }).then(data => {

    uiCtrl.pagination(data, req.query).then((result) => {
      res.status(200).send(result);
    }).catch((error) => {
      console.error(`pagination failed ${error}`);
      res.status(500).send(`pagination failed ${error}`);
    });

  }).catch((error) => {
    console.log(`${origin} ${error}`);
    res.status(404).send('Not found');
  });

});

Вот пользовательская асинхронностьфункция вызывается внутри результата запроса выше.

const uiCtrl = {};

uiCtrl.pagination = async (data, query) => {

  // pagination logic here
  return data;
}

module.exports = uiCtrl;

Ответы [ 2 ]

1 голос
/ 29 мая 2019

Вот переписывание с использованием обычного async/await материала:

var data, results;
try {
   data = await items.find({_id:id}).toArray();
}
catch (err) {
   console.log(`${origin} ${error}`);
   res.status(404).send('Not found');
}
try {
   results = await uiCtrl.pagination(data, req.query);    
}
catch (err) {
   console.error(`pagination failed ${error}`);
   res.status(500).send(`pagination failed ${error}`);
}

Следует отметить, что, учитывая тот факт, что я ничего не знаю о вашем коде, кроме того, что я вижу, возможно, есть и другието, что вы можете сделать, сделает код лучше читаемым и более легким в использовании (то есть отклонение обещания и выполнение с ним чего-то значимого вместо создания исключений).Вам также нужно будет обернуть весь этот код в метод async, чтобы вы могли использовать ключевое слово await.

РЕДАКТИРОВАТЬ

Для завершения, учитывая полноекод, который я сейчас начал бы, переписав его примерно так:

router.get('/:id', async (req, res, next) => {
  const origin = 'routes/items.js GET /:id';

  const id = req.params.id;

  var itemResults, paginationResults;
  try {
     itemResults = await items.find({_id: id}).toArray();
  }
  catch (err) {
     console.log(`${origin} ${error}`);
     res.status(404).send('Not found');
  }
  try {
     paginationResults = await uiCtrl.pagination(data, req.query);
     res.status(200).send(result);
  }
  catch (err) {
     console.error(`pagination failed ${error}`);
     res.status(500).send(`pagination failed ${error}`);
  }
});

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

Также включите это, поскольку в нем говорится о чем-то, что называется callback hell, что очень важно для информации, о которой вы спрашиваете.

http://callbackhell.com/

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

Вот переработанное решение, основанное на принятом ответе.Я получил эту ошибку, я думаю, это связано с размещением ключевого слова async непосредственно в определении маршрутизатора, например router.get('/', async (req, res, next).Возможно, потому что в этом формате он не обрабатывается с помощью then или catch.

(node:3564) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:3564) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Я получил немного измененное решение, я создал функцию-обертку и вызвал ее с помощью then (обработчикСпасибо!

router.get('/', (req, res, next) => {
  const origin = 'routes/items.js GET /';

    async function queryWrapper() {
        let data, results;

        try {
          data = await items.find();
          console.log(`data ${data}`);
        }
        catch (err) {
          console.log(`${origin} ${err}`);
        }
        try {
          results = await uiCtrl.pagination(data, req.query);
        }
        catch (err) {
          console.error(`pagination failed ${err}`);
        }

        if (results) {
          return results;
        } else {
          return false;
        }
      }

      queryWrapper().then((result) => {
        res.status(200).send(result);
      }).catch((error) => {
        console.error(`${error}`);
        res.status(500).send(`${error}`);
      });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...