首页 > 解决方案 > Nodejs等待查询

问题描述

我将 Nodejs 与 MongoDB 一起使用(mongoose 和 express)。

由于我不信任用户数据,因此我需要从数据库中对其进行验证。

输入数据:

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

在我的函数中,我正在验证数据:

router.post("/validate", (req, res,next) =>{
  let validated_data = validate_data(req); 
  console.log(JSON.stringify(validated_data));
  const mydata = new Mydata({
     id: req.body.id,
     lst : validated_data   
  });
  console.log("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(). 但是,该列表可能包含许多元素,我需要等待所有元素都得到验证。

标签: node.jsmongodbexpressmongoosepromise

解决方案


您的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 }
        })
    })

}

如果你愿意,你也可以在这里使用async-await

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
  }

})

推荐阅读