Solución: async/await no funciona dentro de forEach en JavaScript
forEach no espera las promesas de los callbacks async. El código continúa sin esperar a que terminen. Por qué ocurre y cómo iterar arrays de forma asíncrona correctamente.
¿Por qué ocurre?
Array.forEach() fue diseñado para callbacks síncronos. Cuando pasas un callback async, forEach lanza las promesas pero no espera a que resuelvan — simplemente ignora el valor devuelto (una Promise). El bucle completo termina antes de que ninguna operación asíncrona haya finalizado.
Solución paso a paso
El problema:
const ids = [1, 2, 3];// ❌ forEach no espera — imprime "Fin" antes que los usuarios
ids.forEach(async (id) => {
const usuario = await fetchUsuario(id);
console.log(usuario.nombre);
});
console.log('Fin'); // ← esto se ejecuta PRIMERO
Solución A — for...of (espera en secuencia):
// ✅ Cada iteración espera a la anterior (secuencial)
for (const id of ids) {
const usuario = await fetchUsuario(id);
console.log(usuario.nombre);
}
console.log('Fin'); // ← ahora sí se ejecuta al final
Solución B — Promise.all con .map() (paralelo, más rápido):
// ✅ Lanza todas las peticiones a la vez y espera que todas terminen
const usuarios = await Promise.all(
ids.map(id => fetchUsuario(id))
);
usuarios.forEach(u => console.log(u.nombre));
console.log('Fin');
Comparación secuencial vs paralelo:
// Secuencial (for...of): 3 peticiones × 500ms = ~1500ms total
for (const id of ids) {
await fetchUsuario(id); // espera cada una antes de la siguiente
}// Paralelo (Promise.all): 3 peticiones en paralelo = ~500ms total
await Promise.all(ids.map(id => fetchUsuario(id)));
Cuándo usar secuencial vs paralelo:
// Usa for...of cuando el orden importa o una petición depende de la anterior
for (const paso of pasos) {
await ejecutarPaso(paso);
}// Usa Promise.all cuando son independientes (más rápido)
await Promise.all(archivos.map(f => subirArchivo(f)));
// Usa Promise.allSettled si quieres que continúe aunque alguna falle
const resultados = await Promise.allSettled(
ids.map(id => fetchUsuario(id))
);
for...in también tiene el mismo problema:
// ❌ for...in tampoco espera callbacks async (además, no usar con arrays)
// ✅ Usa siempre for...of para iterar arrays de forma asíncrona
Cómo evitarlo en el futuro
Regla simple: si el callback de tu iteración usa `await`, usa `for...of` o `Promise.all` + `.map()`. Nunca `forEach`, `map` suelto sin Promise.all, ni `reduce` para operaciones asíncronas.
¿Quieres que una IA te ayude? Genera el prompt perfecto para tu error:
Generador de Prompts