2016-07-09 15 views
1

参加者の予測をループしていくつかのポイントを計算したいと思います。 プレイヤーが獲得するポイント数を知る(mongooseを使用して)mongodbを呼び出す必要があります。私はこのコードを実行するとhttp://caolan.github.io/async/async foreach call not synchronous node

var calculateTeamPredictionsPerRound = function (roundId) { 
    var roundScores = []; 

    predictions.find({}, {}).exec(function (err, predictions) { 
    console.log("predictions length: " + predictions.length) 
    if (err) return console.error(err); 

    async.each(predictions, 
     function (prediction) { 
     var teamScores = []; 
     console.log("team length: " + prediction.Team.length + "deelnemer: " + prediction.Participant.Name) 

     async.forEach(prediction.Team, function (player,callback) { 
      console.log("for player: " + player.PlayerName + "participant: " + prediction.Participant.Name); 

      teamScore.findOne({ RoundId: roundId, 'Player.Id': player.Id }, { Player: { $elemMatch: { Id: player.Id } } }).exec(function (err, player) { 
      console.log(player.Player[0].Name); 
      var playerScore = new Object; 
      playerScore.Name = player.Player[0].Name; 
      playerScore.Team = player.Player[0].Team; 
      playerScore.Won = setWinScore(player.Player[0]); 
      playerScore.Draw = setDrawScore(player.Player[0]); 
      playerScore.Played = setPlayedScore(player.Player[0]); 
      playerScore.RedCard = setRedCardScore(player.Player[0]); 
      playerScore.YellowCard = setYellowCardScore(player.Player[0]); 
      playerScore.Assist = setAssistScore(player.Player[0]); 
      playerScore.Goals = setGoalScore(player.Player[0]); 
      playerScore.OwnGoal = setOwnGoalScore(player.Player[0]); 
      playerScore.TotalScore = playerScore.Won + playerScore.Draw + playerScore.Played + playerScore.RedCard + playerScore.YellowCard + playerScore.Assist + playerScore.OwnGoal + playerScore.Goals; 
      teamScores.push(playerScore) 
      }); 
      callback();  
     }); 

     }); 
    }); 
}; 

コンソールが私にこのことを示しています:

team length: 11 participant: test 
for player: a participant: test 
for player: b participant: test 
for player: c participant: test 
for player: d participant: test 
for player: e participant: test 
for player: f participant: test 
for player: g participant: test 
for player: h participant: test 
for player: i participant: test 
for player: j participant: test 
for player: k participant: test 
team length: 11participant: test2 
for player: a participant: test2 
for player: b participant: test2 
for player: c participant: test2 
for player: d participant: test2 
for player: e participant: test2 
for player: f participant: test2 
for player: g participant: test2 
for player: h participant: test2 
for player: i participant: test2 
for player: j participant: test2 
for player: k participant: test 
a 
b 
c 
d 
e 
f 
g 
h 
i 
j 
k 
a 
b 
c 
d 
e 
f 
g 
h 
i 
j 
k 
その後、私は参加者ごとのスコアを保存したい

私はこの非同期モジュールを使用しています(後のことを行います)

しかし、私がしたい:

team length: 11participant: test 
for player: a participant: test 
a 
for player: b participant: test 
b 

答えて

0

問題はそのごでありますメソッドでは、非同期でもある.findOne()メソッドを使用します。

実行順序である:

  1. はconsole.log( "プレーヤーのため:" + player.PlayerName + "参加者:" + prediction.Participant.Name)。
  2. findOne()
  3. コールバック()

あなたがfunction (err, player) {...}あるfindOne()のコールバックを待たずに非同期機能のコールバックを()を呼び出します。

function (err, player) {...}の中のcallback()を移動して、非同期タスクを終了する前にfindOne()が実行されるのを待ちます。また

teamScore.findOne({ RoundId: roundId, 'Player.Id': player.Id }, { Player: { $elemMatch: { Id: player.Id } } }).exec(function (err, player) { 
      console.log(player.Player[0].Name); 
      var playerScore = new Object; 
      playerScore.Name = player.Player[0].Name; 
      playerScore.Team = player.Player[0].Team; 
      playerScore.Won = setWinScore(player.Player[0]); 
      playerScore.Draw = setDrawScore(player.Player[0]); 
      playerScore.Played = setPlayedScore(player.Player[0]); 
      playerScore.RedCard = setRedCardScore(player.Player[0]); 
      playerScore.YellowCard = setYellowCardScore(player.Player[0]); 
      playerScore.Assist = setAssistScore(player.Player[0]); 
      playerScore.Goals = setGoalScore(player.Player[0]); 
      playerScore.OwnGoal = setOwnGoalScore(player.Player[0]); 
      playerScore.TotalScore = playerScore.Won + playerScore.Draw + playerScore.Played + playerScore.RedCard + playerScore.YellowCard + playerScore.Assist + playerScore.OwnGoal + playerScore.Goals; 
      teamScores.push(playerScore) 
      callback(); 
      });   
     }); 

、代わりの teamScores.push(playerScore)あなたが callback(playerScore)することができますし、すべてのタスクが完了しているすべてのplayerScoresの配列と呼ばれます async.forEachに最終コールバックを与えます。

async.forEachがthisモジュールの場合は、すべてのタスクが非同期であるため、必要な理由がわかりません。自動的にteamScore.findOne()を同期させるわけではありませんが、var done = this.async();で非同期コールバックを指定し、findOne()が終了したときに呼び出す必要がありますが、代わりに通常のasync.each()を使用することもできます。

+0

私はこのモジュールを使用しています:http://caolan.github.io/async/ –

+0

async.forEachはそのモジュールの一部ではないので、わかりました。async.eachだけです。解決策は同じでなければなりません。 – marton

+0

'forEach'は' each'のエイリアスです – megawac