Array.forEach
no proporciona esta bondad (oh si lo fuera) pero hay varias formas de lograr lo que desea:
Usando un contador simple
function callback () { console.log('all done'); }
var itemsProcessed = 0;
[1, 2, 3].forEach((item, index, array) => {
asyncFunction(item, () => {
itemsProcessed++;
if(itemsProcessed === array.length) {
callback();
}
});
});
(gracias a @vanuan y otros) Este enfoque garantiza que todos los elementos se procesen antes de invocar la devolución de llamada "hecho". Debe usar un contador que se actualice en la devolución de llamada. Dependiendo del valor del parámetro de índice no proporciona la misma garantía, porque el orden de retorno de las operaciones asincrónicas no está garantizado.
Usando promesas ES6
(una biblioteca prometedora se puede utilizar para navegadores antiguos):
Procese todas las solicitudes que garanticen la ejecución síncrona (por ejemplo, 1, luego 2 y 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'))
Procese todas las solicitudes asíncronas sin ejecución "sincrónica" (2 pueden finalizar más rápido que 1)
let requests = [1,2,3].map((item) => {
return new Promise((resolve) => {
asyncFunction(item, resolve);
});
})
Promise.all(requests).then(() => console.log('done'));
Usando una biblioteca asíncrona
Hay otras bibliotecas asincrónicas, asíncronas. es la más popular, que proporcionan mecanismos para expresar lo que desea.
Editar
El cuerpo de la pregunta se ha editado para eliminar el código de ejemplo sincrónico anterior, por lo que he actualizado mi respuesta para aclarar. El ejemplo original usaba código síncrono similar para modelar el comportamiento asíncrono, por lo que se aplica lo siguiente:
array.forEach
es sincrónico y también lo es res.write
, por lo que simplemente puede poner su devolución de llamada después de su llamada a foreach:
posts.foreach(function(v, i) {
res.write(v + ". index " + i);
});
res.end();
forEach
método de matriz estándar tuviera undone
parámetro deallDone
devolución de llamada y una devolución de llamada!