Nodejs ждут запроса

Я использую Nodejs с MongoDB (мангуст вместе с экспресс).

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

входные данные:

{
 "id": "someid",
 "nottrusteddata": [ {"id": "1"}, {"id" :"2"}]
}

В моей функции я проверяю данные:

router.post("/validate", (req, res,next) =>{
  let validated_data = validate_data(req); 
  console.info(JSON.stringify(validated_data));
  const mydata = new Mydata({
     id: req.body.id,
     lst : validated_data   
  });
  console.info("mydata: " + JSON.stringify(mydata));
  /* Some Usefull stuff is here */
  res.status(200).json();
}

function validate_data(req){
 let validated_data = []
 for(let i = 0; i < req.body.nottrusteddata.length; i++)
 {
   Databaseobject.findOne({'id': req.body.nottrusteddata[i].id})
   .exec()
   .then(dbobject =>{
     if (dbobject) // not undefined, it exists in the database
     {
       // Some logic with the object returned from the database
       let tmp_object = {};
       tmpobject.id = dbobject.id;
       // Append it to the list, so that the upper function can use it
       validated_data.push(tmp_object);
     }
   })
 }
 return validated_data;
}

Желаемый вывод должен содержать правильную информацию, поступающую из базы данных, однако из-за асинхронной природы nodejs validated_data возвращает значение null.

Я также пытался использовать Promise. У меня не получилось.

const validate_data = function(req){
  return new Promise(function(resolve,reject){

     let validated_data = []
     for(let i = 0; i < req.body.nottrusteddata.length; i++)
     {
       Databaseobject.findOne({'id': req.body.nottrusteddata[i].id})
       .exec()
       .then(dbobject =>{
         if (dbobject) // not undefined, it exists in the database
         {
           let tmp_object = {};
           tmpobject.id = dbobject.id;
           validated_data.push(tmp_object);
         }
       })
     }
     resolve(validated_data);
  }
}

Что я делаю неправильно? Как я могу дождаться завершения запроса к базе данных, а затем выполнить основную часть? Если бы была только одна проверка, я мог бы использовать .then(). Однако список мог содержать много элементов, и мне нужно дождаться их проверки.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
119
1

Ответы 1

Ваши вызовы Databaseobject.findOne() являются асинхронными, поэтому ваше обещание будет разрешено до того, как любой из них завершится.

Вы можете использовать Promise.all, чтобы дождаться выполнения всех ваших промисов.

Надеюсь, это сработает для вас:

router.post("/validate", (req, res) => {

  validate_data(req.body.nottrusteddata)
    .then(validated_data => {
      const mydata = new Mydata({
        id: req.body.id,
        lst: validated_data   
      })

      // Some useful stuff is here

      res.status(200).json()
    })
    .catch(err => {
      // Handle error
    })

}

function validate_data(nottrusteddata) {

  // Create array of pending promises
  const promises = nottrusteddata
    .map(item => {
      return Databaseobject
        .findOne({ 'id': item.id })
        .exec()
    })

  // Wait for all promises to resolve
  return Promise.all(promises)
    .then(docs => {
      return docs
        .filter(dbobject => dbobject) // Filter out undefined
        .map(dbobject => {
          return { id: dbobject.id }
        })
    })

}

Если хотите, вы также можете использовать здесь асинхронное ожидание:

router.post("/validate", async (req, res) => {

  try {
    const validated_data = await validate_data(req.body.nottrusteddata)

    const mydata = new Mydata({
      id: req.body.id,
      lst: validated_data   
    })

    // Some useful stuff is here

    res.status(200).json()
  }

  catch(err) {
    // Handle error
  }

})

Я не мог выполнить асинхронное ожидание. Просто не дождется. Тем не менее, я ждал, пока все обещания будут выполнены. Асинхронная функция была бы лучше, потому что у меня сложные данные, и каждую часть данных нужно проверять из разных коллекций базы данных. Прямо сейчас я делаю это, и это нормально, но это можно улучшить: check1().then(firstinfo =>{ check2().then(secondinfo =>{...})}) Или мне нужно найти способ дождаться нескольких проверок базы данных, а не выполнять предложения exec.then.

o9339013 23.01.2019 08:09

Если вызовы db не должны быть последовательными, вы можете снова использовать Promise.all(), чтобы запустить их все сразу.

Steve Holgado 23.01.2019 09:27

Другие вопросы по теме