Como sugiere el título. ¿Cómo hago esto?
Quiero llamar whenAllDone()
después de que forEach-loop haya pasado por cada elemento y haya realizado un procesamiento asincrónico.
[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();
}
);
¿Es posible hacer que funcione así? ¿Cuándo el segundo argumento para forEach es una función de devolución de llamada que se ejecuta una vez que pasó por todas las iteraciones?
Rendimiento esperado:
3 done
1 done
2 done
All done!
javascript
node.js
asynchronous
callback
Dan Andreasson
fuente
fuente
forEach
método de matriz estándar tuviera undone
parámetro deallDone
devolución de llamada y una devolución de llamada!Respuestas:
Array.forEach
no proporciona esta bondad (oh si lo fuera) pero hay varias formas de lograr lo que desea:Usando un contador simple
(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)
Procese todas las solicitudes asíncronas sin ejecución "sincrónica" (2 pueden finalizar más rápido que 1)
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.
EditarEl 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 esres.write
, por lo que simplemente puede poner su devolución de llamada después de su llamada a foreach:fuente
if(index === array.length - 1)
y eliminar?itemsProcessed
Si encuentra funciones asincrónicas y desea asegurarse de que antes de ejecutar el código finalice su tarea, siempre podemos utilizar la capacidad de devolución de llamada.
Por ejemplo:
Nota:
functionAfterForEach
es la función que se ejecutará una vez finalizadas las tareas foreach.asynchronous
es la función asincrónica ejecutada dentro de foreach.fuente
Espero que esto solucione su problema, generalmente trabajo con esto cuando necesito ejecutar para cada uno con tareas asincrónicas dentro.
con
fuente
¡Es extraño cuántas respuestas incorrectas se han dado al caso asincrónico ! Se puede mostrar simplemente que la comprobación del índice no proporciona el comportamiento esperado:
salida:
Si verificamos
index === array.length - 1
, se llamará a la devolución de llamada al finalizar la primera iteración, ¡mientras que el primer elemento aún está pendiente!Para resolver este problema sin usar bibliotecas externas como async, creo que su mejor opción es guardar la longitud de la lista y disminuirla después de cada iteración. Dado que solo hay un hilo, estamos seguros de que no hay posibilidad de condición de carrera.
fuente
Con ES2018 puede usar iteradores asíncronos:
fuente
Mi solución sin promesa (esto asegura que cada acción finalice antes de que comience la siguiente):
fuente
fuente
Esta es la solución para Node.js que es asíncrona.
usando el paquete async npm.
(JavaScript) Sincronización para cada bucle con devoluciones de llamada dentro
fuente
Mi solución:
Ejemplo:
fuente
Intento con Easy Way para resolverlo, compártelo contigo:
request
es la función de la biblioteca mssql en el nodo js. Esto puede reemplazar cada función o código que desee. Buena suertefuente
fuente
No debería necesitar una devolución de llamada para recorrer una lista. Simplemente agregue la
end()
llamada después del bucle.fuente
res.write
NO es una operación asincrónica, por lo que su código no funcionará.Una solución simple sería como seguir
fuente
¿Qué tal setInterval, para verificar el recuento completo de iteraciones, trae garantía? no estoy seguro de si no sobrecargará el alcance, pero lo uso y parece ser el indicado
fuente