Array.forEach
ne fournit pas cette finesse (oh si c'est le cas) mais il existe plusieurs façons d'accomplir ce que vous voulez:
Utiliser un simple compteur
function callback () { console.log('all done'); }
var itemsProcessed = 0;
[1, 2, 3].forEach((item, index, array) => {
asyncFunction(item, () => {
itemsProcessed++;
if(itemsProcessed === array.length) {
callback();
}
});
});
(merci à @vanuan et à d'autres) Cette approche garantit que tous les éléments sont traités avant d'appeler le rappel "terminé". Vous devez utiliser un compteur qui est mis à jour dans le rappel. Selon la valeur du paramètre d'index ne fournit pas la même garantie, car l'ordre de retour des opérations asynchrones n'est pas garanti.
Utilisation des promesses ES6
(une bibliothèque de promesses peut être utilisée pour les anciens navigateurs):
Traiter toutes les demandes garantissant une exécution synchrone (par exemple 1 puis 2 puis 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'))
Traiter toutes les demandes asynchrones sans exécution "synchrone" (2 peuvent se terminer plus rapidement que 1)
let requests = [1,2,3].map((item) => {
return new Promise((resolve) => {
asyncFunction(item, resolve);
});
})
Promise.all(requests).then(() => console.log('done'));
Utilisation d'une bibliothèque asynchrone
Il existe d'autres bibliothèques asynchrones, async étant la plus populaire, qui fournissent des mécanismes pour exprimer ce que vous voulez.
Éditer
Le corps de la question a été modifié pour supprimer l'exemple de code précédemment synchrone, j'ai donc mis à jour ma réponse pour clarifier. L'exemple d'origine utilisait du code synchrone pour modéliser le comportement asynchrone, donc les éléments suivants s'appliquaient:
array.forEach
est synchrone et est res.write
donc, vous pouvez donc simplement mettre votre rappel après votre appel à foreach:
posts.foreach(function(v, i) {
res.write(v + ". index " + i);
});
res.end();
forEach
méthode de tableau standard avait undone
paramètre deallDone
rappel et un rappel!