Skip to main content

Introducción al Asincronismo

JavaScript es un lenguaje de programación de un solo hilo (single-threaded), lo que significa que solo puede ejecutar una tarea a la vez. Sin embargo, muchas operaciones como peticiones de red, lectura de archivos o temporizadores toman tiempo. El asincronismo permite que estas operaciones se ejecuten sin bloquear el resto del código.

El Problema: Código Bloqueante

Cuando ejecutas una operación pesada de forma síncrona, bloqueas toda la aplicación:
// Ejemplo de codigo sincronico bloqueante

function heavyFunction() {
  let count = 0;
  for (let i = 0; i < 1000000000; i++) {
    count++;
  }
  console.log("Desbloqueado");
}

const blockButton = document.getElementById("block");

blockButton.addEventListener("click", function () {
  console.log("First step");
  heavyFunction();
  console.log("Last Step");
});
Problema: Mientras heavyFunction() se ejecuta, todo está bloqueado:
  • La interfaz no responde
  • No puedes hacer click en otros botones
  • La página se congela
El código bloqueante crea una experiencia de usuario terrible. Los usuarios pueden pensar que tu aplicación se rompió.

La Solución: Código Asíncrono

Las operaciones asíncronas permiten que el código pesado se ejecute “en segundo plano” sin bloquear:
// Solucion del ejemplo anterior con asincronismo

const noBlockButton = document.getElementById("no-block");

noBlockButton.addEventListener("click", function () {
  console.log("First step");
  setTimeout(function () {
    let count = 0;
    for (let i = 0; i < 1000000000; i++) {
      count++;
    }
    console.log("Desbloqueado");
  }, 0);
  console.log("Last Step");
});
Resultado en la consola:
First step
Last Step
Desbloqueado
¡Nota cómo “Last Step” se imprime antes de “Desbloqueado”! Esto es asincronismo en acción.

setTimeout: Tu Primera Función Asíncrona

setTimeout ejecuta una función después de un retraso especificado (en milisegundos):
// SetTimeOut

const timeOutButton = document.getElementById("timeout");

timeOutButton.addEventListener("click", function () {
  console.log("Inicio del programa");
  setTimeout(() => {
    console.log("Esto se ejecuta después de 2 segundos");
  }, 2000);
  console.log("Fin del programa");
});
Salida:
Inicio del programa
Fin del programa
Esto se ejecuta después de 2 segundos

¿Por qué no se bloquea?

1

JavaScript ejecuta el código línea por línea

Se imprime “Inicio del programa”.
2

Encuentra setTimeout

En lugar de esperar 2 segundos, JavaScript:
  • Programa la función para ejecutarse después
  • Continúa inmediatamente con la siguiente línea
3

Continúa la ejecución

Se imprime “Fin del programa”.
4

Después de 2 segundos

La función programada se ejecuta e imprime “Esto se ejecuta después de 2 segundos”.

El Event Loop

JavaScript usa un event loop (bucle de eventos) para manejar asincronismo:
╭──────────────╮
│  Call Stack  │ ← Código que se está ejecutando ahora
╰──────────────╯

╭──────────────╮
│  Web APIs   │ ← setTimeout, fetch, etc.
╰──────────────╯

╭──────────────╮
│ Callback    │ ← Funciones esperando ejecutarse
│ Queue       │
╰──────────────╯

    Event Loop verifica:
    ¿Call Stack vacío? → Mueve callback al Call Stack

Cómo Funciona

  1. Call Stack: Donde se ejecuta el código actualmente
  2. Web APIs: Donde viven las funciones asíncronas (setTimeout, fetch, etc.)
  3. Callback Queue: Cola de funciones listas para ejecutarse
  4. Event Loop: Mueve funciones de la cola al call stack cuando está vacío
Esto explica por qué setTimeout(fn, 0) no ejecuta la función inmediatamente - debe esperar a que el call stack esté vacío.

Operaciones Asíncronas Comunes

Temporizadores

setTimeout(), setInterval()

Peticiones de Red

fetch(), XMLHttpRequest

Eventos

Clicks, teclado, mouse

Sistema de Archivos

Lectura/escritura (en Node.js)

Por Qué Necesitamos Asincronismo

Cuando pides datos a un servidor, puede tomar segundos. Sin asincronismo, tu aplicación se congelaría esperando la respuesta.
// Sin asincronismo (bloqueante)
const datos = obtenerDatosDelServidor(); // Bloquea aquí por segundos
console.log(datos);

// Con asincronismo (no bloqueante)
obtenerDatosDelServidor().then(datos => {
    console.log(datos);
});
console.log('Esto se ejecuta inmediatamente');
Los usuarios esperan que las interfaces respondan instantáneamente. El asincronismo permite que la UI permanezca responsive mientras se procesa trabajo pesado.
Puedes iniciar múltiples operaciones asíncronas al mismo tiempo:
// Iniciar 3 peticiones al mismo tiempo
const promesa1 = fetch('/api/usuarios');
const promesa2 = fetch('/api/productos');
const promesa3 = fetch('/api/ordenes');

// Esperar a que todas terminen
Promise.all([promesa1, promesa2, promesa3]).then(resultados => {
    console.log('Todas las peticiones completadas');
});

Patrones Asíncronos en JavaScript

JavaScript ofrece tres formas principales de manejar asincronismo:
  1. Callbacks - La forma original (puede llevar a “callback hell”)
  2. Promises - Una mejor forma de manejar operaciones asíncronas
  3. Async/Await - La forma más moderna y legible
Cada uno tiene sus ventajas y casos de uso. En las siguientes secciones, exploraremos cada uno en detalle.
La mayoría del código JavaScript moderno usa async/await, pero es importante entender callbacks y promises porque los verás en código existente.

Próximos Pasos

Callbacks

Aprende el patrón más básico de asincronismo

Promises

Descubre una mejor forma de manejar asincronismo

Async/Await

La forma más moderna y limpia

Ejemplos Prácticos

Ve ejemplos completos en acción

Build docs developers (and LLMs) love