Array.forEach
n'offre pas cette possibilité (si seulement elle l'offrait), mais il existe plusieurs façons de réaliser ce que vous souhaitez :
Utilisation d'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'invoquer le callback "done". Vous devez utiliser un compteur qui est mis à jour dans le callback. Dépendre de la valeur du paramètre index n'offre 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 navigateurs plus anciens) :
-
Traiter toutes les demandes en 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 vite 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, asynchrone les plus populaires, qui fournissent des mécanismes permettant d'exprimer ce que l'on veut.
Editer
Le corps de la question a été modifié pour supprimer l'exemple de code synchrone, j'ai donc mis à jour ma réponse pour la clarifier. L'exemple original utilisait un code synchrone pour modéliser un comportement asynchrone :
array.forEach
es synchrone et il en est de même pour res.write
Vous pouvez donc simplement placer votre callback après votre appel à foreach :
posts.foreach(function(v, i) {
res.write(v + ". index " + i);
});
res.end();