2017-08-09 54 views
0

我正在處理一個問題,我需要查詢數據庫的選民實例,並使用該實例更新選舉,返回到原始功能,無論該更新是否成功或不。我的代碼目前看起來是這樣的:從異步調用返回Mongoose查詢結果

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; 
       }); 
      } 
     } 
    ); 
} 

我已經嘗試打印出選民實例(r.voter),以檢查它是否存在(它) ,並打印出由貓鼬呼叫返回的選舉對象,這也起作用。但是,無論調用的結果如何,我都會得到一個空值,其值爲

addedCandidatesSucessfully = _addCandidateToElection(electionName, candidates[i]); 

行。我認爲它與mongoose調用有關,返回一個本地值,該值永遠不會返回到調用_addCandidateToElection的函數,但我不知道該如何返回。我試圖把控制標誌,如

let foundAndUpdatedElection = false; 

上_addCandidateToElection的第一行,並更新它的貓鼬查詢的回調中,但顯然它不會改變。 我該如何將查詢結果返回給addCandidatesToElection函數?

回答

0

您應該'promisify'您的代碼,以幫助您更好地處理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'); 
    }); 
} 

你也將不再需要,因爲承諾現在是在本土ES6

+0

意想不到的答案,謝謝使用異步庫!我正在考慮使用Promises,但是在藍鳥和Mongoose自己的承諾實施之間我有點失落。但是這樣更具可讀性,正如你所說的,它捆綁了ES6,這非常棒。在有人讀這個的情況下,我還必須修改if(err)在findVoter到if(err ||!voter)的行,否則Mongoose將在稍後嘗試將null值推送到Promise數組。除此之外,與這個答案瞭解了很多,謝謝:) –

+0

很高興它幫助! – ruedamanuel