Saltar al contenido principal
JavaScript

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.

Error: async/await no funciona dentro de forEach

¿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.

JavaScriptasyncpromesasarraysError

¿Quieres que una IA te ayude? Genera el prompt perfecto para tu error:

Generador de Prompts

¿Necesitas desarrollo a medida?

Apps web, IA, módulos ERP — cuéntame tu proyecto.