2017-08-16 2 views
1

Sagen wir, wir haben ein Modell "Benutzer" und ein Modell "Spiel".Nodejs - Was ist die Reihenfolge der Ausführung in diesem Code? Async warten innen für Schleife

Ein Benutzer kann viele Spiele haben, aber ein Spiel gehört nur einem Benutzer.

In "user" Modell, haben wir Feld "gamesCount" - die insgesamt Spiel, dass Benutzer

In "Spiele" -Modell hat, haben wir Feld userId - im Zusammenhang mit Benutzern

Jetzt müssen wir Schleife durch alle Benutzer, und für jeden Benutzer fragen wir die "Spiel" Sammlung, um zu erhalten, wie viele Spiele dieser Benutzer hat, dann speichern Sie den Wert "gamesCount" zum Benutzermodell.

Ich habe 2 Code-Schnipsel:

updateUserGamesCount: async function (req, res) { 
    try { 
     let users = await User.find({}); 
     for (let user of users) { 
      user.gamesCount= await Game.count({userId: user._id}); 
      await user.save(); 
     } 
     return res.status(200).send("Success"); 
    } catch (err) { 
     res.status(500).send(err); 
    } 
} 

Dieses erste Snippet funktioniert nicht. Es lädt nur für eine Weile und fordert dann eine Auszeit an. Wenn ich den Wert von gamesCount ändern wollte, um zu sehen, ob er aktualisiert wurde oder nicht, wird der Wert nach diesem ersten Snippet-Lauf nicht aktualisiert.

updateUserGamesCount: async function (req, res) { 
    try { 
     let users = await User.find({}); 
     for (let user of users) { 
      user.gamesCount= await Game.count({userId: user._id}); 
      user.save(); 
     } 
     return res.status(200).send("Success"); 
    } catch (err) { 
     res.status(500).send(err); 
    } 
} 

Dieser zweite Ausschnitt funktioniert. Der einzige Unterschied ist im zweiten Snippet, ich entferne die Wartezeit vor user.save();

Warum passiert das? Ich dachte, dass user.save() asynchron ist und wir müssen warten? Und was genau ist die Reihenfolge der Ausführung in dieser Codezeile?

Vielen Dank.

+0

Was bedeutet "nicht funktioniert"? Gibt 'User.save' ein Versprechen zurück? –

+0

@StephenCleary: Ich habe meine Frage aktualisiert.Es lädt nur für eine Weile und fordert dann eine Auszeit an. Als ich versuchte, den Wert von gamesCount zu ändern, um zu sehen, ob er aktualisiert wurde oder nicht, wird der Wert nach diesem ersten Snippet-Lauf nicht aktualisiert. –

Antwort

2

Q: Warum funktioniert das erste Code-Snippet und nicht das andere?

A: Ich denke, wir klar auf der Definition von ‚es funktioniert‘ sein müssen. Es funktionierte, weil kein Fehler geworfen wurde?

Ich vermute, dass Ihr 2. Code-Snippet überhaupt nicht funktioniert, sondern Sie maskieren nur den Fehler, indem Sie das await Schlüsselwort entfernen.

Das erste Beispiel Arbeit, weil Sie für die save Betrieb wieder das Warten durch den try Block zu beenden, bevor er auf und wenn ein exception geworfen wird, dann wird es gefangen. Während der 2. Code nicht mehr auf die Antwort save() wartet und einfach success zurückgibt. Wenn diese Theorie zutrifft, dann sollte nichts saved erfolgreich sein. Ob es funktioniert oder nicht, nur die Datenbank kann die Wahrheit sagen. Das erste Code-Snippet ist der richtige Ansatz, aber es kann eine bessere Leistung erzielt werden.

Betrachten Sie alle save Versprechen zu bündeln und eine promise.all(...) für möglich Leistungsgewinn tun. Alternativ kann auch die Durchführung einer Operation, die alle Änderungen einschließt, eine gute Option in bestimmten Anwendungsfällen sein.

Siehe: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

+0

Vielen Dank @Samuel Toh. Eigentlich habe ich gesagt, dass das zweite Snippet funktioniert, denn wenn ich die Datenbank überprüfe, sind alle Werte von gamesCount korrekt. Ich bin nicht sicher, wie ist das –

+0

Angenommen, Sie haben eine 'saubere' Datenbank für jeden Lauf. Wenn Sie den ersten Code ausführen, wird überhaupt nichts aufgefüllt? oder war es etwas? Wenn es das letztere ist, dann könnte es möglicherweise ein intermittierendes Probem sein. –

+0

Nein Ich habe versucht, den Wert einiger Datensätze in falsche Werte zu ändern. Dann führe ich das zweite Snippet aus. Als ich diese Werte erneut überprüft habe, sind sie korrekt. Deshalb muss ich diese Frage stellen, weil es keinen Sinn macht mit dem, was ich über Promise oder async gelernt habe/erwarte –

Verwandte Themen