Volver al inicio
Lección 12

⏱️ Asincronía en JavaScript

Aprende qué es la programación asíncrona y por qué es fundamental para crear aplicaciones web modernas. Entiende cómo JavaScript maneja tareas que toman tiempo.

1. Código síncrono (normal)

El código síncrono se ejecuta línea por línea, en orden. Cada línea espera a que la anterior termine antes de ejecutarse.

sincrono.jsjavascript
1console.log('1. Inicio');
2console.log('2. Procesando...');
3console.log('3. Fin');
4
5// Salida:
6// 1. Inicio
7// 2. Procesando...
8// 3. Fin

✅ Ventaja:

Es fácil de entender: el código se ejecuta de arriba hacia abajo, en el orden que lo escribiste.

❌ Problema:

Si una operación tarda mucho (como cargar datos de un servidor), todo se detiene hasta que termine.

1console.log('Inicio');
2
3// Imagina que esto tarda 5 segundos
4const datos = cargarDatosDelServidor();
5
6console.log('Fin'); // Espera 5 segundos antes de mostrarse
7
8// ⏱️ La página queda "congelada" 5 segundos

2. Código asíncrono (no bloqueante)

El código asíncrono permite que el programa continúe ejecutándose mientras espera que termine una tarea lenta.

Es como pedirle a alguien que haga café mientras tú sigues trabajando. No te quedas parado esperando, continúas con otras cosas.

Visualización interactiva:

Observa cómo se ejecuta el código síncrono vs asíncrono. Las cajas resaltadas muestran qué línea se está ejecutando:

Código Síncrono

Paso 1: Empezar
Paso 2: Tarea que tarda 5 seg
TODO bloqueado esperando...
Paso 3: Terminar
Ejecutando

Código Asíncrono

Paso 1: Empezar
Paso 2: Programar tarea (5 seg)
Se ejecutará después en segundo plano
Paso 3: Terminar (no espera)
Continúa inmediatamente
Paso 2 completado (después)
La tarea programada terminó
Ejecutando sin pausas

💡 Nota: En el código síncrono, todo se detiene en la tarea lenta. En el asíncrono, el programa continúa y ejecuta el callback cuando la tarea termina.

3. setTimeout - Tu primera función asíncrona

setTimeout() ejecuta código después de un tiempo, sin bloquear el resto del programa.

Sintaxis:

1setTimeout(function() {
2 // Código a ejecutar
3}, milisegundos);

Ejemplo básico:

setTimeout-basico.jsjavascript
1console.log('1. Inicio');
2
3setTimeout(function() {
4 console.log('2. Esto se ejecuta después de 2 segundos');
5}, 2000);
6
7console.log('3. Fin');
8
9// Salida:
10// 1. Inicio
11// 3. Fin
12// (espera 2 segundos)
13// 2. Esto se ejecuta después de 2 segundos

⚠️ ¡Importante!

Observa que "3. Fin" se muestra ANTES que el mensaje del setTimeout, aunque está escrito después. Esto es porque setTimeout es asíncrono.

Con arrow function:

setTimeout-arrow.jsjavascript
1console.log('Preparando café...');
2
3setTimeout(() => {
4 console.log('☕ ¡El café está listo!');
5}, 3000);
6
7console.log('Mientras tanto, sigo trabajando...');
8
9// Salida:
10// Preparando café...
11// Mientras tanto, sigo trabajando...
12// (espera 3 segundos)
13// ☕ ¡El café está listo!

Visualización de setTimeout:

Observa cómo setTimeout espera el tiempo especificado antes de ejecutar el callback:

Preparar café de forma asíncrona

Mientras el agua se calienta (3 segundos), podemos hacer otras cosas

0ms750ms1500ms2250ms3000ms
1. Calentar agua
(setTimeout 3s)
2, 3, 4. Otras tareas
(mientras espera)
¡Agua lista!
(callback ejecutado)
console.log('1. Poner agua a calentar...');
setTimeout(() => {
console.log('💧 El agua está lista');
}, 3000);
console.log('2. Moler el café...');
console.log('3. Preparar la cafetera...');
console.log('4. Hacer otras cosas...');
// Salida de consola:
> 1. Poner agua a calentar...
> 2. Moler el café...
> 3. Preparar la cafetera...
> 4. Hacer otras cosas...
> (el agua sigue calentándose en segundo plano...)
> 💧 El agua está lista
> ☕ ¡Ahora sí, a preparar el café!

4. Callbacks - Funciones que se ejecutan después

Un callback es una función que pasas como parámetro a otra función, para que se ejecute cuando termine una tarea.

Ejemplo simple:

callback-simple.jsjavascript
1function hacerAlgo(callback) {
2 console.log('Haciendo algo...');
3 callback();
4}
5
6// Pasar una función como callback
7hacerAlgo(function() {
8 console.log('¡Terminé!');
9});
10
11// Salida:
12// Haciendo algo...
13// ¡Terminé!

Ejemplo con setTimeout:

callback-ejemplo.jsjavascript
1function descargarDatos(callback) {
2 console.log('📥 Descargando datos...');
3
4 setTimeout(() => {
5 const datos = { nombre: 'Juan', edad: 25 };
6 callback(datos);
7 }, 2000);
8}
9
10// Llamar con un callback
11descargarDatos(function(datos) {
12 console.log('✅ Datos recibidos:', datos);
13});
14
15console.log('Mientras tanto hago otras cosas...');
16
17// Salida:
18// 📥 Descargando datos...
19// Mientras tanto hago otras cosas...
20// (espera 2 segundos)
21// ✅ Datos recibidos: { nombre: 'Juan', edad: 25 }

💡 ¿Por qué usar callbacks?

  • Para ejecutar código cuando una tarea termine
  • Para manejar datos que llegan de forma asíncrona
  • Para responder a eventos (clicks, datos de servidor, etc.)

5. El problema: Callback Hell

Cuando necesitas hacer varias tareas asíncronas una después de otra, los callbacks se anidan y el código se vuelve difícil de leer.

callback-hell.jsjavascript
1// ❌ Callback Hell (pirámide del infierno)
2obtenerUsuario(function(usuario) {
3 obtenerPedidos(usuario.id, function(pedidos) {
4 obtenerDetalles(pedidos[0].id, function(detalles) {
5 obtenerProductos(detalles.productos, function(productos) {
6 console.log('Productos:', productos);
7 // Difícil de leer y mantener
8 });
9 });
10 });
11});

Problemas del Callback Hell:

  • Código difícil de leer (forma de pirámide)
  • Difícil de mantener y debuggear
  • Difícil manejar errores

✅ Solución:

En las próximas lecciones veremos Promises y async/await, que resuelven este problema de forma elegante.

6. ¿Cómo funciona? El Event Loop

JavaScript es single-threaded (un solo hilo), pero puede hacer múltiples cosas gracias al Event Loop.

Funcionamiento simplificado:

  1. 1. JavaScript ejecuta el código línea por línea
  2. 2. Cuando encuentra una tarea asíncrona (setTimeout, fetch, etc.), la envía al navegador
  3. 3. JavaScript continúa ejecutando el resto del código
  4. 4. Cuando la tarea asíncrona termina, su callback se añade a la cola
  5. 5. Cuando JavaScript termina todo el código síncrono, ejecuta los callbacks de la cola
event-loop.jsjavascript
1console.log('1. Inicio'); // Síncrono
2
3setTimeout(() => {
4 console.log('2. Callback asíncrono');
5}, 0); // Aunque sea 0 ms, va a la cola
6
7console.log('3. Fin'); // Síncrono
8
9// Salida:
10// 1. Inicio
11// 3. Fin
12// 2. Callback asíncrono
13
14// Aunque setTimeout tenga 0ms, se ejecuta DESPUÉS
15// porque primero termina todo el código síncrono

Visualización del Event Loop:

Observa cómo el Event Loop maneja las tareas asíncronas a través del Call Stack, Web APIs y Callback Queue:

Event Loop en Acción

Call Stack
console.log('1')
Web APIs
Callback Queue

1Ejecutando código síncrono: console.log('Inicio')

Ejercicio práctico

Simular carga de datos

Crea una función que simule cargar datos de un usuario con un setTimeout.

Requisitos:

  1. Crea una función llamada cargarUsuario(callback)
  2. Usa setTimeout para simular 2 segundos de carga
  3. Devuelve un objeto usuario con nombre y email usando el callback
  4. Muestra un mensaje mientras carga
Ver solución
solucion.jsjavascript
1function cargarUsuario(callback) {
2 console.log(' Cargando usuario...');
3
4 setTimeout(() => {
5 const usuario = {
6 nombre: 'María López',
7 email: 'maria@example.com'
8 };
9
10 callback(usuario);
11 }, 2000);
12}
13
14// Usar la función
15console.log('Inicio');
16
17cargarUsuario(function(usuario) {
18 console.log(' Usuario cargado:', usuario.nombre);
19 console.log(' Email:', usuario.email);
20});
21
22console.log('Haciendo otras cosas mientras carga...');
23
24// Salida:
25// Inicio
26// Cargando usuario...
27// Haciendo otras cosas mientras carga...
28// (espera 2 segundos)
29// Usuario cargado: María López
30// Email: maria@example.com

📚 Resumen

Síncrono

Línea por línea, bloqueante

Simple pero lento para tareas largas

Asíncrono

No bloqueante, continúa ejecutando

Perfecto para tareas que toman tiempo

setTimeout

Ejecuta código después de X tiempo

setTimeout(fn, ms)

Callbacks

Funciones que se ejecutan al terminar

Útiles pero pueden crear "callback hell"

Próxima lección: Veremos XMLHttpRequest (la forma vieja de hacer peticiones) para entender por qué Fetch es tan importante.