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
function callback () { console.log('all done'); }
var itemsProcessed = 0;
[1, 2, 3].forEach((item, index, array) => {
asyncFunction(item, () => {
itemsProcessed++;
if(itemsProcessed === array.length) {
callback();
}
});
});
(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).
function asyncFunction (item, cb) {
setTimeout(() => {
console.log('done with', item);
cb();
}, 100);
}
let requests = [1, 2, 3].reduce((promiseChain, item) => {
return promiseChain.then(() => new Promise((resolve) => {
asyncFunction(item, resolve);
}));
}, Promise.resolve());
requests.then(() => console.log('done'))
Verarbeiten Sie alle asynchronen Anforderungen ohne "synchrone" Ausführung (2 werden möglicherweise schneller als 1 beendet).
let requests = [1,2,3].map((item) => {
return new Promise((resolve) => {
asyncFunction(item, resolve);
});
})
Promise.all(requests).then(() => console.log('done'));
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.
Bearbeiten
Der 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 auch res.write
, so dass Sie Ihren Rückruf einfach nach Ihrem Anruf an foreach senden können:
posts.foreach(function(v, i) {
res.write(v + ". index " + i);
});
res.end();
forEach
Methode einendone
Rückrufparameter und einenallDone
Rückruf hätte!