【问题标题】:returning Mongoose query result from Async call从异步调用返回 Mongoose 查询结果
【发布时间】:2018-01-17 22:05:39
【问题描述】:

我正在解决一个问题,我需要在数据库中查询选民的实例,并使用该实例更新选举,无论更新是否成功,都返回到原始函数。我的代码目前如下所示:

function addCandidatesToElection(req, res) {
    let electionName = req.body.electionName;
    let candidates = req.body.candidates;
    let addedCandidatesSucessfully = true;
    for(let i=0; i<candidates.length; i++) {
        addedCandidatesSucessfully = _addCandidateToElection(electionName, candidates[i]);
        console.log("added candidates sucessfully:" + addedCandidatesSucessfully);
    }
    if(addedCandidatesSucessfully) {
        res.send("createElection success");
    } else {
        res.send("createElection fail");
    }
}

调用这个函数:

function _addCandidateToElection(electionName, candidateName) {
    async.parallel(
    {
        voter: function(callback) {
            Voter.findOne({ 'name' : candidateName }, function(err,voter) {
                callback(err, voter);
            });
        }
    },
    function(e, r) {
        if(r.voter === null){ 
            return 'Voter not found';
        } else {
            Election.findOneAndUpdate(
            {'name': electionName },
            {$push: { candidates: r.voter }},
            {new: true},
            function(err, election) {
                if(err){ return err; } 
                return (election) ? true : false;
                });
            }
        }
    );
}

我已经尝试打印出 Voter 实例 (r.voter) 以检查它是否存在(确实存在),并打印出由 mongoose 调用返回的选举对象,这也有效。但是,我在

中得到了一个空值
addedCandidatesSucessfully = _addCandidateToElection(electionName, candidates[i]);

line,不管调用的结果如何。我认为这与 mongoose 调用返回一个本地值有关,该值永远不会返回到调用 _addCandidateToElection 的函数中,但我不知道应该如何返回它。我尝试过放置控制标志,例如

let foundAndUpdatedElection = false;

在 _addCandidateToElection 的第一行并在 Mongoose 查询的回调中更新它,但显然它没有改变。 如何将查询结果返回给 addCandidatesToElection 函数?

【问题讨论】:

    标签: node.js mongodb express mongoose async.js


    【解决方案1】:

    您可能应该“承诺”您的代码,以帮助您更好地处理 js 的异步特性。尝试以下代替您的示例:

    function findVoter(candidateName) {
      return new Promise(function(resolve, reject) {
        Voter.findOne({ 'name' : candidateName }, function(err,voter) {
          if(error) {
            reject(error);
          } else { 
            resolve(voter);
          }
        });
      });
    }
    
    function addCandidateToElection(electionName, candidateName) {
      return findVoter(candidateName).then(function(voter) {
        return new Promise(function(resolve, reject) {
            Election.findOneAndUpdate(
              {'name': electionName },
              {$push: { candidates: voter }},
              {new: true},
              function(err, election) {
                if (err) {
                  reject(err);
                } else {
                  resolve(!!election);
                }
              });
      });
    }
    
    function addCandidatesToElection(req, res) {
      let electionName = req.body.electionName;
      let candidates = req.body.candidates;
      let addedCandidatesSucessfully = true;
      let candidatePromiseArray = [];
      for(let i=0; i<candidates.length; i++) {
        candidatePromiseArray.push(addCandidateToElection(electionName, candidates[i]));
      }
      Promise.all(candidatePromiseArray)
        .then(function(results) {
          console.log(results);
          res.send('create election success');
        })
        .catch(function(error) {
          console.error(error);
          res.send('failed');
        });
    }
    

    您也将不再需要使用异步库,因为 promise 现在在 ES6 中是原生的

    【讨论】:

    • 很棒的答案,谢谢!我正在考虑使用 Promises,但我在 bluebird 和 Mongoose 自己的 Promise 实现之间有点迷失了。但这更具可读性,并且正如您所说,它与 ES6 捆绑在一起,非常棒。如果有人正在阅读本文,我还必须将 findVoter 上的 if(err) 行修改为 if(err || !voter),否则 Mongoose 会在稍后尝试将空值推送到 Promises 数组时中断。除此之外,通过这个答案学到了很多东西,谢谢:)
    • 很高兴它有帮助!
    猜你喜欢
    • 2014-07-20
    • 2023-04-01
    • 2020-11-25
    • 2022-12-22
    • 2021-10-16
    • 2021-07-22
    • 2015-12-07
    • 2015-04-09
    • 2020-03-15
    相关资源
    最近更新 更多