NodeJS - контроллер - несколько запросов из коллекций + forEach - PullRequest
0 голосов
/ 05 мая 2018

Беспорядок с обещаниями и асинхронностью и ожиданием. Хотели бы получить ваш совет, какова лучшая практика для случая ниже контроллера? Теперь он не получит данные пользователя перед передачей данных клиенту.

Я делаю просто конечную точку API на стороне сервера с NodeJS. Контроллер делает два запроса, чтобы просто выполнить результаты в виде объекта json для клиента. Да, это бесполезный массив run [], но он используется при построении целых результатов события:)

exports.runresults3 = function(req, res) {

  // Route is passing ID
  console.log('id', req.params.id);

  // Test results object to fill
  const resultsParams = {
    run: [{
      runid: {},
      endtimeid: [],
      userid: [],
      endtime: [],
      username: [],
    }]
  }

  // Run objectid
  resultsParams.run[0].runid = req.params.id;

  // Get the endtimes by location/stage
  Endtime.find({stage: req.params.id})
    .then(data => {
      // First loop
      data.forEach(value => {
        resultsParams.run[0].endtimeid.push(value._id);
        resultsParams.run[0].userid.push(value.user);
        resultsParams.run[0].endtime.push(value.endtime);
      })
    })
    .then(() => {
      // Second loop to get user details for results object
      resultsParams.run[0].userid.forEach((userId, i) => {
        TempUser.findById(userId)
          .then(userdetails => {
            console.log('userdetails.name', userdetails.name);
            resultsParams.run[0].username.push(userdetails.name);
          });
      })
    })
    .then(() => {
      res.json(resultsParams);
    });
}

//////////// клиентская сторона получит JSON следующим образом

{
"run": [
    {
        "runid": "5ae850d51717862590dc30d4",
        "endtimeid": [
            "5aec482d98555332145eccd3",
            "5aec48c098555332145eccd6",
            "5aec4a2c98555332145eccda",
            "5aec4ab398555332145eccdd",
            "5aec4bb998555332145ecce1",
            "5aec4e42c3bcbb196c8474fc",
            "5aec4e44c3bcbb196c8474fe",
            "5aec4e45c3bcbb196c847500"
        ],
        "userid": [
            "5aec13b098555332145eccbe",
            "5ae869c797e54a37f498c98f",
            "5aec4a1298555332145eccd7",
            "5aec4a1298555332145eccd7",
            "5aec4ba698555332145eccde",
            "5aec13a598555332145eccbc",
            "5ae869c797e54a37f498c98f",
            "5aec13b098555332145eccbe"
        ],
        "endtime": [
            24424,
            3280,
            11858,
            38874,
            5738,
            40384,
            50906,
            36717
        ],
        "username": []
    }
]

}

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

Вот отредактированные версии в соответствии с рекомендациями :) Но все еще не хватает сведений о пользователе, похоже, что promise.all не ожидает запроса "TempUser.findById (record.user)".

1 Я создал новое событие, запустил, 3 пользователя и 3 результата.

2 Затем я установил несколько журналов по вызовам БД.

3 Тогда я сделал запрос на получение с почтальоном

Журнал с localhost выглядит так после GET-запроса Postman:

$ узел приложения Сервер запущен на 5000 Mongodb подключен id 5aeebd8a1b5ddf1424c25194

  1. Получить время окончания работы с базой данных

[{создано: 2018-05-06T08: 32: 46,359Z, _id: 5aeebdae1b5ddf1424c25199, конечное время: 23204, пользователь: 5aeebd751b5ddf1424c25191, этап: 5aeebd8a1b5ddf1424c25194, __v: 0}, {создано: 2018-05-06T08: 32: 49.414Z, _id: 5aeebdb11b5ddf1424c2519b, конечное время: 17149, пользователь: 5aeebd7b1b5ddf1424c25192, этап: 5aeebd8a1b5ddf1424c25194, __v: 0}, {создано: 2018-05-06T08: 32: 51.769Z, _id: 5aeebdb31b5ddf1424c2519d, конечное время: 10840, пользователь: 5aeebd7f1b5ddf1424c25193, этап: 5aeebd8a1b5ddf1424c25194, __v: 0}]

  1. Установить результаты для объекта

[не определено, не определено, не определено] Это должно быть последним в цепочке?

  1. Получить информацию о пользователе из базы данных

{дата: 2018-05-06T08: 31: 49,673Z, _id: 5aeebd751b5ddf1424c25191, имя: 'Firstame Lastname1', __v: 0} 2. Получить информацию о пользователе из базы данных {дата: 2018-05-06T08: 31: 55.562Z, _id: 5aeebd7b1b5ddf1424c25192, имя: 'Firstame Lastname2', __v: 0} 2. Получить информацию о пользователе из базы данных {дата: 2018-05-06T08: 31: 59,906Z, _id: 5aeebd7f1b5ddf1424c25193, имя: 'Firstame Lastname3', __v: 0}

Это делается с помощью следующего кода:

exports.runresults3 = function(req, res) {

  // Route is passing ID
  console.log('id', req.params.id);
  
  // Test results object to fill
  const resultsParams = {
    run: [{
      runid: {},
      results: []
    }]
  }

  // Each run objectid
  resultsParams.run[0].runid = req.params.id;

  Endtime.find({stage: req.params.id})
    .then(data => {
      console.log('1. Get endtimes from database', data);
      return Promise.all(data.map(record => {
        TempUser.findById(record.user)
          .then(userdetails => {
            console.log('2. Get user details from database', userdetails);
            return {
              endtimeid: record._id,
              userid: record.user,
              endtime: record.endtime,
              username: userdetails.name
            };
          })
      }))
    })
    .then(results => { 
      console.log('3. Set results to object', results);
      console.log('This should be the last one at chain?');
      
      resultsParams.run[0].results = results;
    })
    .then(() => res.json(resultsParams));
}
0 голосов
/ 05 мая 2018

exports.runresults3 = function(req, res) {

  // Route is passing ID
  console.log('id', req.params.id);

  // Test results object to fill
  const resultsParams = {
    run: [{
      runid: {},
      endtimeid: [],
      userid: [],
      endtime: [],
      username: [],
    }]
  }

  // Run objectid
  resultsParams.run[0].runid = req.params.id;

  Endtime.find({stage: req.params.id})
    .then(data => {
      return Promise.all(data.map(record => {
        TempUser.findById(record.user)
          .then(userdetails => {
            return {
              endtimeid: record._id,
              userid: record.user,
              endtime: record.endtime,
              username: userdetails.name
            };
          })
      }))
      .then(detailRecords => {
        return detailRecords.reduce((acc, curr) => {
          acc.endtimeid.push(curr.endtimeid);
          acc.userid.push(curr.userid);
          acc.endtime.push(curr.endtime);
          acc.username.push(curr.username);
          return acc;
        },resultsParams.run[0]);
      })
      .then(() => {
        res.json(resultsParams);
      });
    });
}

Если у вас есть требование накапливать вещи в стиле «ассоциативный массив» вещей в этом результирующем объекте, вероятно, я бы так и сделал.

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

{
  "run": [
    {
      "runid": "5ae850d51717862590dc30d4",
      "results": [
        {
          "endtimeid": "5aec482d98555332145eccd3",
          "userid": "5aec13b098555332145eccbe",
          "endtime": 24424,
          "username": "User123"
        },
        {
          "endtimeid": "5aec48c098555332145eccd6",
          "userid": "5ae869c797e54a37f498c98f",
          "endtime": 3280,
          "username": "User234"
        }
      ]
    }
  ]
}

Я полагаю, что следующий код должен сделать это.

exports.runresults3 = function(req, res) {

  // Route is passing ID
  console.log('id', req.params.id);

  // Test results object to fill
  const resultsParams = {
    run: [{
      runid: {},
      results: []
    }]
  }

  // Run objectid
  resultsParams.run[0].runid = req.params.id;

  Endtime.find({stage: req.params.id})
    .then(data => {
      return Promise.all(data.map(record => {
        TempUser.findById(record.user)
          .then(userdetails => {
            return {
              endtimeid: record._id,
              userid: record.user,
              endtime: record.endtime,
              username: userdetails.name
            };
          })
      }))
    })
    .then(results => resultsParams.run[0].results = reuslts)
    .then(() => res.json(resultsParams));
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...