Array.forEach
não fornece essa gentileza (se assim for), mas há várias maneiras de realizar o que você deseja:
Usando um contador simples
function callback () { console.log('all done'); }
var itemsProcessed = 0;
[1, 2, 3].forEach((item, index, array) => {
asyncFunction(item, () => {
itemsProcessed++;
if(itemsProcessed === array.length) {
callback();
}
});
});
(obrigado a @vanuan e outros) Essa abordagem garante que todos os itens sejam processados antes de chamar o retorno de chamada "concluído". Você precisa usar um contador que seja atualizado no retorno de chamada. Dependendo do valor do parâmetro index, não fornece a mesma garantia, porque a ordem de retorno das operações assíncronas não é garantida.
Usando as promessas do ES6
(uma biblioteca de promessas pode ser usada para navegadores mais antigos):
Processe todas as solicitações que garantam a execução síncrona (por exemplo, 1 e 2 e 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'))
Processe todas as solicitações assíncronas sem execução "síncrona" (2 podem terminar mais 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 uma biblioteca assíncrona
Existem outras bibliotecas assíncronas, async sendo as mais populares, que fornecem mecanismos para expressar o que você deseja.
Editar
O corpo da pergunta foi editado para remover o código de exemplo anteriormente síncrono. Atualizei minha resposta para esclarecer. O exemplo original usava o código síncrono para modelar o comportamento assíncrono; portanto, o seguinte se aplica:
array.forEach
é síncrono e assim é res.write
, para que você possa simplesmente colocar seu retorno de chamada após sua ligação para foreach:
posts.foreach(function(v, i) {
res.write(v + ". index " + i);
});
res.end();
forEach
método de matriz padrão tivessedone
parâmetro deallDone
retorno de chamada e retorno de chamada!