Como o título sugere. Como eu faço isso?
Quero ligar whenAllDone()
depois que o loop forEach passou por cada elemento e fez algum processamento assíncrono.
[1, 2, 3].forEach(
function(item, index, array, done) {
asyncFunction(item, function itemDone() {
console.log(item + " done");
done();
});
}, function allDone() {
console.log("All done");
whenAllDone();
}
);
É possível fazê-lo funcionar assim? Quando o segundo argumento para forEach é uma função de retorno de chamada que é executada depois de todas as iterações?
Saída esperada:
3 done
1 done
2 done
All done!
javascript
node.js
asynchronous
callback
Dan Andreasson
fonte
fonte
forEach
método de matriz padrão tivessedone
parâmetro deallDone
retorno de chamada e retorno de chamada!Respostas:
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
(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)
Processe todas as solicitações assíncronas sem execução "síncrona" (2 podem terminar mais rápido que 1)
Usando uma biblioteca assíncrona
Existem outras bibliotecas assíncronas, async sendo as mais populares, que fornecem mecanismos para expressar o que você deseja.
EditarO 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:fonte
if(index === array.length - 1)
e removaitemsProcessed
Se você encontrar funções assíncronas e quiser ter certeza de que, antes de executar o código, ele conclui sua tarefa, sempre podemos usar o recurso de retorno de chamada.
Por exemplo:
Nota:
functionAfterForEach
é a função a ser executada após a conclusão das tarefas foreach.asynchronous
é a função assíncrona executada dentro do foreach.fonte
Espero que isso resolva o seu problema, geralmente trabalho com isso quando preciso executar o forEach com tarefas assíncronas dentro.
com
fonte
É estranho quantas respostas incorretas foram dadas ao caso assíncrono ! Pode-se simplesmente mostrar que a verificação do índice não fornece o comportamento esperado:
resultado:
Se procurarmos
index === array.length - 1
, o retorno de chamada será chamado após a conclusão da primeira iteração, enquanto o primeiro elemento ainda estiver pendente!Para resolver esse problema sem usar bibliotecas externas, como async, acho que sua melhor aposta é economizar o comprimento da lista e diminuir se após cada iteração. Como há apenas um tópico, temos certeza de que não há chance de condição de corrida.
fonte
Com o ES2018, você pode usar iteradores assíncronos:
fonte
Minha solução sem promessa (isso garante que todas as ações sejam encerradas antes do início da próxima):
fonte
fonte
Esta é a solução para o Node.js que é assíncrona.
usando o pacote async npm.
(JavaScript) Sincronizando o loop forEach com retornos de chamada dentro
fonte
Minha solução:
Exemplo:
fonte
Tento o Easy Way para resolvê-lo e compartilhá-lo com você:
request
é a função da biblioteca mssql no nó js. Isso pode substituir cada função ou código que você deseja. Boa sortefonte
fonte
Você não precisa de um retorno de chamada para iterar através de uma lista. Basta adicionar a
end()
chamada após o loop.fonte
res.write
NÃO é uma operação assíncrona, portanto seu código não funcionará.Uma solução simples seria como seguir
fonte
Que tal setInterval, para verificar a contagem completa de iterações, traz garantia. Não tenho certeza se ele não sobrecarregará o escopo, mas eu o uso e parece ser o único
fonte