Tema 20 · Asincronía

Promesas y Asincronía Básica

Comprende el modelo asíncrono no bloqueante de JavaScript: el Event Loop, el ciclo de vida de una Promesa (pending, fulfilled, rejected) y el encadenamiento con .then() y .catch().

¿Por qué JavaScript es Asíncrono?

JavaScript opera sobre un único hilo de ejecución (single-threaded). Para evitar que operaciones lentas (como consultar una base de datos o solicitar datos a un servidor) congelen la interfaz de usuario, JavaScript delega estas tareas al navegador mediante su mecanismo de Event Loop (Bucle de Eventos).

Diagrama Técnico: Arquitectura del Event Loop y Asincronía en JavaScript

Diagrama 20.1: El flujo del Event Loop: Call Stack, Web APIs, Microtask Queue (Promesas) y Callback Queue.

Los Tres Estados de una Promesa

Una Promesa es un objeto que representa la terminación o el fracaso de una operación asíncrona a futuro:

Estado Significado Método de Captura
Pending (Pendiente) La operación ha iniciado pero aún no ha finalizado ni fallado. Estado inicial.
Fulfilled (Cumplida) La operación concluyó con éxito y tiene un resultado disponible. .then(resultado => ...)
Rejected (Rechazada) Ocurrió un error o la operación no pudo completarse. .catch(error => ...)

Construcción y Consumo de una Promesa

const verificarStock = (cantidad) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (cantidad <= 10) {
        resolve(`Stock confirmado para ${cantidad} unidades.`);
      } else {
        reject(new Error("Cantidad supera el stock disponible en bodega."));
      }
    }, 1500);
  });
};

// Consumo con encadenamiento .then() y .catch()
verificarStock(5)
  .then(mensaje => console.log("Éxito:", mensaje))
  .catch(error => console.error("Fallo:", error.message))
  .finally(() => console.log("Verificación finalizada."));

⚡ Simulador de Solicitud de Pedido con Promesas

Simula una petición asíncrona a un servidor remoto con resolución o rechazo controlado por una Promesa:

index.html
Solo lectura
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <title>Promesas en JavaScript</title>
  <style>
    body { font-family: Arial, Helvetica, sans-serif; padding: 25px; background: #f8fafc; }
    .card-promesa { max-width: 500px; background: white; border: 1px solid #cbd5e1; border-radius: 8px; padding: 22px; }
    .grupo-acciones { display: flex; gap: 8px; margin-bottom: 15px; }
    button { padding: 9px 14px; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; }
    .btn-exito { background: #16a34a; color: white; }
    .btn-fallo { background: #dc2626; color: white; }
    button:disabled { opacity: 0.5; cursor: not-allowed; }
    .visor-estado { padding: 15px; border-radius: 6px; font-family: monospace; background: #f1f5f9; border-left: 4px solid #64748b; font-size: 0.9rem; min-height: 48px; display: flex; align-items: center; }
    .estado-pending { border-color: #f59e0b; background: #fffbeb; color: #b45309; }
    .estado-fulfilled { border-color: #22c55e; background: #f0fdf4; color: #166534; }
    .estado-rejected { border-color: #ef4444; background: #fef2f2; color: #991b1b; }
  </style>
</head>
<body>

  <div class="card-promesa">
    <h3 style="margin-top: 0; color: #0f172a;">Simulador de Promesas</h3>
    <p style="color: #64748b; font-size: 0.9rem;">Prueba solicitar una respuesta asíncrona (espera simulada de 1.5 segundos):</p>

    <div class="grupo-acciones">
      <button class="btn-exito" id="btn-ok" onclick="ejecutarPromesa(true)">Simular Respuesta Exitosa</button>
      <button class="btn-fallo" id="btn-bad" onclick="ejecutarPromesa(false)">Simular Error de Servidor</button>
    </div>

    <div class="visor-estado" id="caja-estado">Presiona un botón para crear una Promesa (Promise).</div>
  </div>

  <script>
    function crearPromesaSimulada(debeTriunfar) {
      return new Promise((resolve, reject) => {
        // Simulamos latencia de red de 1.5s
        setTimeout(() => {
          if (debeTriunfar) {
            resolve({ codigo: 200, mensaje: "¡Matrícula confirmada en Kilopolis!" });
          } else {
            reject(new Error("Error 500: Tiempo de espera agotado en la base de datos."));
          }
        }, 1500);
      });
    }

    function ejecutarPromesa(debeTriunfar) {
      const visor = document.getElementById('caja-estado');
      const btnOk = document.getElementById('btn-ok');
      const btnBad = document.getElementById('btn-bad');

      btnOk.disabled = true;
      btnBad.disabled = true;

      visor.className = "visor-estado estado-pending";
      visor.textContent = "⏳ Estado: PENDING (esperando respuesta del servidor)...";

      crearPromesaSimulada(debeTriunfar)
        .then(datos => {
          // Estado FULFILLED
          visor.className = "visor-estado estado-fulfilled";
          visor.textContent = `✓ Estado: FULFILLED -> ${datos.mensaje}`;
        })
        .catch(err => {
          // Estado REJECTED
          visor.className = "visor-estado estado-rejected";
          visor.textContent = `✕ Estado: REJECTED -> ${err.message}`;
        })
        .finally(() => {
          btnOk.disabled = false;
          btnBad.disabled = false;
        });
    }
  </script>

</body>
</html>
Pruébalo tú mismo » Se abre en una nueva pestaña con ejecución en vivo
🧠
Mini-Quiz de Retención
Comprueba tu comprensión antes de pasar a la siguiente lección
1 Pregunta
Pregunta 1
¿En qué orden se imprimirán los mensajes del siguiente código en la consola? console.log("A"); setTimeout(() => console.log("B"), 0); Promise.resolve().then(() => console.log("C")); console.log("D");
🦉
¿Tienes dudas con este tema?
Sócrates AI puede darte analogías y explicarte este código paso a paso.

🚀 ¿Quieres dominar Manual Completo de JavaScript ES6+ y crear proyectos reales?

Aprende arquitectura limpia, desarrollo web moderno, buenas prácticas y despliegue en producción con nuestro Bootcamp Fullstack Developer con mentorías en vivo.

🏛️ Autoría y Propiedad Intelectual: Obra educativa original de David Amador para Kilopolis Academia (Solucionáticos), estructurada sobre las especificaciones y estándares abiertos del W3C, el estándar vivo de WHATWG y la documentación oficial de código abierto. © Todos los derechos reservados.