如何使用带有承诺的异步等待获取我的结果?

时间:2019-11-07 10:51:14

标签: node.js foreach promise async-await synchronous

我有一个应该返回结果的函数,

我有一个在其上进行foreach的数组,并且我从数据库中获取了一个函数,该函数对数组中的每个id都有一个承诺, 调用此最后一个函数时,我使用async等待,但是最终结果将在执行函数之前返回。

控制器用户

myFunction: function (req, res) {
    let headerAuth = req.headers['authorization'];
    let login = utils.getUser(headerAuth);
    if (login) {
        //some function to get data from database
        ModelUsers.getData(login, function (err1, result) {
            if (!err1) {
                let data = [];
                result.forEach(async function (r) {
                    //function with promise, see next
                    let dataxx = await ModelUsers.getDataWithPromise(r._id);
                    data.push(dataxx);
                    console.log("**dataxx : ", dataxx)
                })

                res.json({ success: true, data: data })
            }
        })


    }
},

 ** Model Users **

module.exports.getDataWithPromise = function(id) {
    return new Promise((resolve, reject) => {

        Users.findOne({ _id: id })

            .exec(function (err, doc) {
                resolve(doc)
            })

    })

}

我收到一个空结果,并且在控制台中,成功返回呼叫后,我得到了显示的结果

{
    "success": true,
    "data": []
}
GET /users/myFunction 200 21.379 ms - 26
**dataxx :  {mydata:[{"a": 1, "b":2}, {"c":3, "d":4}]}

我如何获得结果?

4 个答案:

答案 0 :(得分:1)

将foreach循环更改为for循环并按预期工作

myFunction: function (req, res) {
let headerAuth = req.headers['authorization'];
let login = utils.getUser(headerAuth);
if (login) {
    //some function to get data from database
    ModelUsers.getData(login, async function (err1, result) {
        if (!err1) {
            let data = [];
            for (let index = 0; index < result.length; index++) {
                const element = result[index];
                let dataxx = await ModelUsers.getDataWithPromise(r._id);
                data.push(dataxx);
            }
            res.json({ success: true, data: data })
        }
    })


}

答案 1 :(得分:1)

您可以通过以下两种方式解决此问题:

if (login) {
  //some function to get data from database
  ModelUsers.getData(login, function(err1, result) {
    if (!err1) {
      let data = [];
      result.forEach(async function(r, idx) {
        //function with promise, see next
        let dataxx = await ModelUsers.getDataWithPromise(r._id);
        data.push(dataxx);
        console.log("**dataxx : ", dataxx)
        if (result.length === idx + 1) {
          res.json({
            success: true,
            data: data
          })
        }
      })
    }
  })
}

OR

if (login) {
  //some function to get data from database
  ModelUsers.getData(login, async function(err1, result) {
      if (!err1) {
        let data = [];
        for (const r of result) {
          //function with promise, see next
          let dataxx = await ModelUsers.getDataWithPromise(r._id);
          data.push(dataxx);
          console.log("**dataxx : ", dataxx)
        })
      res.json({
        success: true,
        data: data
      })
    }
  })
}

答案 2 :(得分:1)

forEach是异步的。在这种情况下,可以使用forfor of循环为同步for of循环。我加了一个例子。请注意async回调中的getData关键字。

  myFunction: function(req, res) {
   let headerAuth = req.headers['authorization'];
   let login = utils.getUser(headerAuth);
   if (login) {
     //some function to get data from database
     ModelUsers.getData(login, async function(err1, result) {
       if (!err1) {
         let data = [];

         for (let user of result) {
           let dataxx = await ModelUsers.getDataWithPromise(r._id);
           data.push(dataxx);
         }

         res.json({ success: true, data: data })
       }
     })


   }
 }

答案 3 :(得分:1)

forEach方法不支持async函数。您可以使用Array.map来完成技巧,将每个值转换为一个承诺,然后等待它们以Promise.all完成:

ModelUsers.getData(login, async function (err1, result) {
    if (!err1) {
        const data = await Promise.all(result.map(({_id}) => ModelUsers.getDataWithPromise(_id)))
        res.json({success: true, data})
    }
})