2016-07-09 4 views
1

Ich möchte einige Vorhersagen der Teilnehmer durchlaufen und einige Punkte berechnen. Um zu wissen, wie viele Punkte ein Spieler bekommt, muss ich mongodb anrufen (mit Mungo). Dann möchte ich pro Teilnehmer die Noten speichern (wird tun, dass später)Async Foreach Call nicht synchronen Knoten

ich dieses async Modul bin mit: http://caolan.github.io/async/

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

     }); 
    }); 
}; 

Wenn ich diesen Code ausführen die Konsole zeigt mir dies:

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 

Aber ich will:

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

Antwort

0

Das Problem ist, dass in Ihrem async.forEach Methode verwenden Sie eine .findOne() Methode, die auch asynchron ist.

Die Ausführungsreihenfolge ist:

  1. console.log ("für den Spieler:" + player.PlayerName + "Teilnehmer:" + prediction.Participant.Name);
  2. FindOne()
  3. Rückruf()

Sie rufen Rückruf() von der Asynchron-Funktion für den Rückruf von FindOne ohne warten(), die function (err, player) {...} ist.

Verschieben Sie callback() innerhalb von function (err, player) {...}, um darauf zu warten, dass findOne() ausgeführt wird, bevor die asynchrone Task beendet wird.

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

Auch anstelle von teamScores.push(playerScore) Sie können callback(playerScore), und dann einen endgültigen Rückruf async.forEach geben, die mit einem Array aller playerScores aufgerufen werden, wenn alle Aufgaben abgeschlossen sind.

Wenn async.forEach ist this Modul, ich bin mir nicht sicher, warum Sie es brauchen, da alle Ihre Aufgaben asynchron sind. Es macht nicht automatisch teamScore.findOne() synchron, Sie müssen immer noch einen asynchronen Callback mit var done = this.async(); angeben und es aufrufen, wenn findOne() fertig ist, aber Sie können stattdessen auch einfach das reguläre async.each() verwenden.

+0

Ich verwende dieses Modul: http://caolan.github.io/async/ –

+0

Ok, ich war nur verwirrt, weil async.forEach nicht Teil dieses Moduls ist, nur async.each. Lösung sollte gleich sein. – marton

+0

'forEach' ist ein Alias ​​von' each' – megawac