Event Loop y Call Stack: Entendiendo cómo JavaScript ejecuta tu código
El Event Loop es el corazón del modelo de concurrencia de JavaScript 🧠. Aunque el lenguaje es single-threaded (solo puede ejecutar una cosa a la vez), su arquitectura permite manejar tareas asíncronas de manera fluida. ¿Magia? No, pura ingeniería. ✨
⚙️ El motor detrás: Call Stack (Pila de llamadas)
El Call Stack es donde JavaScript ejecuta tu código línea por línea. Cada vez que se llama a una función, esta se “apila”. Cuando termina, se “desapila”.
function uno() {
console.log("1️⃣ Uno");
dos();
console.log("1️⃣ Fin de Uno");
}
function dos() {
console.log("2️⃣ Dos");
}
uno();
🧩 Salida:
1️⃣ Uno
2️⃣ Dos
1️⃣ Fin de Uno
📚 Todo ocurre de forma sincrónica — es decir, una cosa detrás de la otra.
⏳ Cuando entra la asincronía
Pero ¿qué pasa con funciones como setTimeout, fetch o addEventListener?
Estas no se ejecutan directamente en el Call Stack, sino que el navegador o el entorno (Node.js) las delega a su
sistema interno.
console.log("Inicio 🟢");
setTimeout(() => console.log("Timeout ⏰"), 0);
console.log("Fin 🔴");
🧩 Salida:
Inicio 🟢
Fin 🔴
Timeout ⏰
🤔 ¿Por qué el setTimeout se ejecuta al final si el tiempo era 0?
Aquí entra en juego el protagonista: el Event Loop.
🔁 El Event Loop en acción
El Event Loop (bucle de eventos) es quien coordina cuándo las tareas pueden volver al Call Stack.
Imagina esta escena:
| Elemento | Función | Analogía |
|---|---|---|
| Call Stack | Ejecuta las funciones activas. | El chef cocinando ahora mismo. 👨🍳 |
| Task Queue (cola de tareas) | Guarda callbacks listos para ejecutarse (como setTimeout). | Los pedidos esperando su turno. 🧾 |
| Event Loop | Supervisa y mueve tareas de la cola al stack cuando esté libre. | El maître que organiza los pedidos. 🍽️ |
Cuando el Call Stack está vacío, el Event Loop toma la primera tarea de la cola y la ejecuta.
⚡ Microtareas vs. Macrotareas
JavaScript no tiene una sola cola, sino dos principales:
| Tipo | Ejemplo | Prioridad |
|---|---|---|
| Microtasks | Promise.then(), queueMicrotask() | 🔥 Alta |
| Macrotasks | setTimeout, setInterval, setImmediate | 🕐 Menor |
🔍 Esto significa que las promesas se ejecutan antes que los setTimeout, incluso si ambos están listos.
Ejemplo:
console.log("Inicio 🟢");
setTimeout(() => console.log("Macrotarea ⏰"), 0);
Promise.resolve().then(() => console.log("Microtarea 🔥"));
console.log("Fin 🔴");
🧩 Salida:
Inicio 🟢
Fin 🔴
Microtarea 🔥
Macrotarea ⏰
🧩 Orden de ejecución en un ejemplo mixto
console.log("1️⃣");
setTimeout(() => console.log("2️⃣ Timeout"), 0);
Promise.resolve()
.then(() => console.log("3️⃣ Promise 1"))
.then(() => console.log("4️⃣ Promise 2"));
console.log("5️⃣ Fin del script");
🧩 Salida:
1️⃣
5️⃣ Fin del script
3️⃣ Promise 1
4️⃣ Promise 2
2️⃣ Timeout
📊 Explicación:
- El código sincrónico se ejecuta primero (líneas 1 y 5).
- Las promesas se van a la cola de microtareas y se ejecutan justo después.
- El
setTimeoutse ejecuta finalmente como una macrotarea.
🧩 ¿Por qué importa entender esto?
Entender el Event Loop te permite:
- 🧩 Escribir código más eficiente y evitar bloqueos.
- ⚡ Anticipar el orden real de ejecución en código asíncrono.
- 🐞 Depurar comportamientos “raros” de promesas o
setTimeout.
💡 Buenas prácticas
✅ No bloquees el Call Stack con tareas pesadas.
✅ Usa Promise y async/await en lugar de anidar setTimeout.
✅ Aprende a distinguir entre microtareas y macrotareas.
🎯 Conclusión
El Event Loop es el verdadero director de orquesta de JavaScript 🎻.
Aunque el lenguaje solo ejecuta una cosa a la vez, gracias a este sistema puede coordinar tareas, eventos y promesas sin detener el flujo principal.
Entenderlo no solo mejora tu código… también te convierte en un mejor JavaScript developer. 🚀