Wie der Titel schon sagt. Wie mache ich das?
Ich möchte aufrufen, whenAllDone()
nachdem die forEach-Schleife jedes Element durchlaufen und eine asynchrone Verarbeitung durchgeführt hat.
[1, 2, 3].forEach(
function(item, index, array, done) {
asyncFunction(item, function itemDone() {
console.log(item + " done");
done();
});
}, function allDone() {
console.log("All done");
whenAllDone();
}
);
Möglich, dass es so funktioniert? Wenn das zweite Argument für forEach eine Rückruffunktion ist, die ausgeführt wird, sobald alle Iterationen durchlaufen wurden?
Erwartete Ausgabe:
3 done
1 done
2 done
All done!
javascript
node.js
asynchronous
callback
Dan Andreasson
quelle
quelle
forEach
Methode einendone
Rückrufparameter und einenallDone
Rückruf hätte!Antworten:
Array.forEach
bietet diese Freundlichkeit nicht (oh, wenn es so wäre), aber es gibt verschiedene Möglichkeiten, um das zu erreichen, was Sie wollen:Mit einem einfachen Zähler
(Dank an @vanuan und andere) Dieser Ansatz garantiert, dass alle Elemente verarbeitet werden, bevor der Rückruf "erledigt" aufgerufen wird. Sie müssen einen Zähler verwenden, der im Rückruf aktualisiert wird. Abhängig vom Wert des Indexparameters wird nicht die gleiche Garantie gegeben, da die Reihenfolge der Rückgabe der asynchronen Operationen nicht garantiert ist.
ES6-Versprechen verwenden
(Eine Versprechensbibliothek kann für ältere Browser verwendet werden):
Verarbeiten Sie alle Anforderungen, die eine synchrone Ausführung gewährleisten (z. B. 1, dann 2, dann 3).
Verarbeiten Sie alle asynchronen Anforderungen ohne "synchrone" Ausführung (2 werden möglicherweise schneller als 1 beendet).
Verwenden einer asynchronen Bibliothek
Es gibt andere asynchrone Bibliotheken, von denen Async am beliebtesten ist und die Mechanismen bieten, um auszudrücken, was Sie wollen.
BearbeitenDer Hauptteil der Frage wurde bearbeitet, um den zuvor synchronen Beispielcode zu entfernen. Daher habe ich meine Antwort zur Verdeutlichung aktualisiert. Im ursprünglichen Beispiel wurde synchroner Code verwendet, um asynchrones Verhalten zu modellieren. Daher gilt Folgendes:
array.forEach
ist synchron und so ist es auchres.write
, so dass Sie Ihren Rückruf einfach nach Ihrem Anruf an foreach senden können:quelle
if(index === array.length - 1)
und entfernenitemsProcessed
Wenn Sie auf asynchrone Funktionen stoßen und sicherstellen möchten, dass der Code vor der Ausführung seiner Aufgabe beendet wird, können wir jederzeit die Rückruffunktion verwenden.
Beispielsweise:
Hinweis:
functionAfterForEach
Ist die Funktion, die ausgeführt werden soll, nachdem alle Aufgaben abgeschlossen sind.asynchronous
ist die asynchrone Funktion, die in foreach ausgeführt wird.quelle
Hoffe, dies wird Ihr Problem beheben, ich arbeite normalerweise damit, wenn ich forEach mit asynchronen Aufgaben ausführen muss.
mit
quelle
Es ist seltsam, wie viele falsche Antworten auf asynchrone Fälle gegeben wurden! Es kann einfach gezeigt werden, dass das Überprüfen des Index nicht das erwartete Verhalten liefert:
Ausgabe:
Wenn wir nach prüfen
index === array.length - 1
, wird der Rückruf nach Abschluss der ersten Iteration aufgerufen, während das erste Element noch aussteht!Um dieses Problem zu lösen, ohne externe Bibliotheken wie Async zu verwenden, ist es meiner Meinung nach am besten, die Länge der Liste zu speichern und zu dekrementieren, wenn nach jeder Iteration. Da es nur einen Thread gibt, sind wir sicher, dass es keine Chance auf Rennbedingungen gibt.
quelle
Mit ES2018 können Sie asynchrone Iteratoren verwenden:
quelle
Meine Lösung ohne Versprechen (dies stellt sicher, dass jede Aktion beendet wird, bevor die nächste beginnt):
quelle
quelle
Dies ist die asynchrone Lösung für Node.js.
Verwenden des asynchronen npm-Pakets.
(JavaScript) Synchronisieren der forEach-Schleife mit darin enthaltenen Rückrufen
quelle
Meine Lösung:
Beispiel:
quelle
Ich versuche Easy Way, um es zu lösen, teile es mit dir:
request
ist die Funktion der mssql-Bibliothek in Node js. Dies kann jede gewünschte Funktion oder jeden gewünschten Code ersetzen. Viel Glückquelle
quelle
Sie sollten keinen Rückruf benötigen, um eine Liste zu durchlaufen. Fügen Sie einfach den
end()
Anruf nach der Schleife hinzu.quelle
res.write
ist KEINE asynchrone Operation, daher funktioniert Ihr Code nicht.Eine einfache Lösung wäre wie folgt
quelle
Wie wäre es mit setInterval, um die vollständige Iterationszahl zu überprüfen, bringt Garantie. Ich bin mir nicht sicher, ob es den Bereich nicht überlasten wird, aber ich benutze es und scheint es zu sein
quelle