【问题标题】:Nodejs wait for queryNodejs等待查询
【发布时间】:2019-06-16 10:44:53
【问题描述】:

我在 MongoDB 中使用 Nodejs(猫鼬和 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.js mongodb express mongoose promise


    【解决方案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 }
            })
        })
    
    }
    

    如果你愿意,你也可以在这里使用 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
      }
    
    })
    

    【讨论】:

    • 我不能做异步等待。它只是不等待。然而,我已经等待所有的承诺都完成了。异步功能会更好,因为我有复杂的数据,并且需要从不同的数据库集合中检查数据的每一部分。现在,我正在这样做,这很好,但可以改进:check1().then(firstinfo =&gt;{ check2().then(secondinfo =&gt;{...})}) 或者,我需要找到一种方法来等待多个数据库检查,而不是执行exec.then 子句
    • 如果数据库调用不需要顺序,那么您可以再次使用Promise.all() 一次运行它们。
    猜你喜欢
    • 2020-06-19
    • 2015-10-24
    • 2019-04-19
    • 2019-05-25
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-30
    相关资源
    最近更新 更多