Skip to content

L56 - Event Loop

JavaScript es un lenguaje single-threaded (un solo hilo de ejecución). Esto significa que solo puede ejecutar una tarea a la vez. El Event Loop es el mecanismo que permite a JavaScript manejar operaciones asíncronas (timers, peticiones de red, eventos del DOM) sin bloquear el hilo principal.

Es una estructura LIFO (Last In, First Out) que almacena las funciones en ejecución. Cuando se llama a una función, se apila; cuando retorna, se desapila.

function a() { b(); }
function b() { c(); }
function c() { console.log('Hola'); }
a();
// Stack: a → b → c → (se ejecuta c) → sale c → sale b → sale a

Son funciones proporcionadas por el navegador (o Node.js) que se ejecutan fuera del hilo principal: setTimeout, fetch, DOM events, requestAnimationFrame, etc. Cuando se invocan, el callback correspondiente se registra en la Web API y se programa para más tarde.

Callback Queue (Cola de tareas / Macrotask Queue)

Section titled “Callback Queue (Cola de tareas / Macrotask Queue)”

Aquí llegan los callbacks de las Web APIs cuando están listos para ejecutarse: los timers cuando expiran, los eventos cuando ocurren, las respuestas de fetch cuando llegan.

El Event Loop observa constantemente si el Call Stack está vacío. Si lo está, toma el primer callback de la cola y lo pasa al Call Stack para que se ejecute.

console.log('1'); // Síncrono → se ejecuta inmediatamente
setTimeout(() => {
console.log('2'); // Asíncrono → va a Web API, luego a la cola
}, 0);
console.log('3'); // Síncrono → se ejecuta inmediatamente

¿Qué imprime?

1
3
2
  1. console.log('1') → se apila, se ejecuta, se desapila. Output: 1.
  2. setTimeout(cb, 0) → se apila, la Web API registra el timer con 0ms, el callback pasa a la cola. Se desapila.
  3. console.log('3') → se apila, se ejecuta, se desapila. Output: 3.
  4. El Call Stack está vacío. El Event Loop toma el callback de setTimeout de la cola y lo pasa al stack.
  5. console.log('2') → se ejecuta. Output: 2.
console.log('Inicio');
setTimeout(() => {
console.log('setTimeout 1');
}, 1000);
setTimeout(() => {
console.log('setTimeout 0');
}, 0);
console.log('Fin');
// ¿Qué imprime y en qué orden?
// 1. Inicio
// 2. Fin
// 3. setTimeout 0 (aunque el delay es 0, pasa por la cola)
// 4. setTimeout 1 (después de 1 segundo)

⚠️ setTimeout(fn, 0) no es instantáneo: retrasa la ejecución hasta que el Call Stack esté vacío y todas las tareas previas se hayan completado.

console.log('1');
fetch('/api/datos')
.then(res => res.json())
.then(data => console.log('3', data));
console.log('2');
// 1
// 2
// 3 (cuando la petición termine)

La petición fetch se inicia en una Web API, y cuando la respuesta llega, su .then() va a la microtask queue (lo veremos en la siguiente lección).

📝 ¿Por qué es importante entender el Event Loop?

Section titled “📝 ¿Por qué es importante entender el Event Loop?”
  1. Depuración: entender por qué ciertas cosas ocurren en un orden inesperado.
  2. Rendimiento: operaciones pesadas bloquean el Call Stack y congelan la UI.
  3. Código asíncrono: saber cuándo se ejecuta realmente tu código te evita bugs sutiles.
  4. Animaciones y UI: necesitas saber que el renderizado del navegador ocurre entre tareas.
// Esto bloquea el Event Loop y congela la UI
function bloquear() {
const start = Date.now();
while (Date.now() - start < 5000) {
// ocupado 5 segundos
}
}
bloquear(); // La UI se congela 5 segundos

🎯 Regla de oro: nunca ejecutes operaciones síncronas pesadas en el hilo principal. Usa Web Workers para tareas intensivas.

Call Stack (JS) ←→ Web APIs (Timer, Fetch, DOM)
↑ ↓
Event Loop ←→ Callback Queue (Macrotasks)

El Event Loop mantiene a JS siendo single-threaded pero no bloqueante, permitiendo que las operaciones asíncronas se “sientan” como si ocurrieran en paralelo.