🌐 1.10 · Async, Promises y Fetch: hablar con servidores

⏱ 6h 00min ⚡ 100 XP 🏅 Aprendiz 📖 Fundamentos del Web FullStack
"JavaScript es asíncrono por naturaleza. Aprender async/await es aprender a pensar como la web."

🎯 Objetivo del tema

Al terminar este tema serás capaz de: Al terminar este tema serás capaz de explicar por qué JavaScript es asíncrono, usar Promises y async/await para manejar operaciones que toman tiempo, hacer peticiones HTTP a servidores con la API Fetch, y manejar errores de forma robusta. Tu frontend podrá pedir datos al backend sin recargar la página.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

🗺️ Mapa del tema

Hasta ahora, tu código JavaScript se ejecuta de arriba a abajo, una línea tras otra. Pero muchas operaciones de la web TOMAN TIEMPO: pedir datos a un servidor, leer un archivo, esperar un temporizador. Si JavaScript se quedara 'esperando' esas operaciones, la página se congelaría. La solución: asincronía. Hoy aprenderás las 3 formas modernas: callbacks (histórico), Promises, y async/await (la estrella).

1. El problema: el código asíncrono

Por qué JavaScript no puede simplemente 'esperar' y qué pasa cuando lo intenta.

2. Callbacks y el callback hell

La forma histórica (y por qué casi nadie la usa ya en código nuevo).

3. Promises: la primera solución elegante

Un objeto que representa un valor que ESTARÁ disponible en el futuro.

4. async/await: código asíncrono que se lee sincrónico

La forma moderna. Tu código se lee como si fuera sincrónico pero NO bloquea la página.

5. Fetch API: peticiones HTTP modernas

Cómo pedirle datos a un servidor desde el navegador.

6. Manejo de errores: try/catch y .catch()

Qué hacer cuando algo falla: red caída, servidor caído, JSON inválido.

7. Frameworks JS: React, Vue, Angular y Svelte en el horizonte

Por qué existen los frameworks, comparativa honesta, y cuándo usar cada uno en tu carrera.

1.10.1 El problema: el código asíncrono

JavaScript es un lenguaje de UN SOLO HILO: ejecuta una cosa a la vez. Si le pides que 'espere 3 segundos a que llegue un dato del servidor', TODO lo demás se congela: la página no responde, los botones no hacen clic, las animaciones se detienen. Por eso JavaScript necesita asincronía: operaciones que empiezan, dejan 'una nota pendiente' y siguen ejecutando el resto del código.

El ejemplo del restaurante

Imagina un mesero en un restaurante. Si tomara tu pedido, fuera a la cocina, ESPERARA parado hasta que el plato esté listo, y volviera a tu mesa, el restaurante perdería toda la clientela. En cambio, el mesero toma tu pedido, lo deja en cocina, va a atender otras mesas, y cuando el plato está listo lo recoge. Eso es asincronía.

Las 3 operaciones asíncronas más comunes

OperaciónPor qué es asíncronaTiempo típico
Petición HTTP (fetch)Viaja por la red hasta el servidor y de vuelta.50ms - 5s.
setTimeout / setIntervalEspera un tiempo antes de ejecutar.Variable.
Lectura de archivosLee del disco duro o de la red.10ms - varios segundos.
Eventos del usuarioEspera a que el usuario interactúe.Indefinido.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

1.10.2 Callbacks y el callback hell

La forma HISTÓRICA de manejar asincronía en JavaScript: pasar una función (callback) que se ejecuta CUANDO la operación termina. Funciona, pero cuando encadenas muchas operaciones, el código se vuelve ilegible: el famoso 'callback hell' (infierno de callbacks).

// Ejemplo: leer usuario, luego sus pedidos, luego sus productos
getUser(userId, function(user) {
  getOrders(user.id, function(orders) {
    getProducts(orders[0].id, function(products) {
      console.log(products);
    }, function(errorProductos) {
      console.error(errorProductos);
    });
  }, function(errorOrders) {
    console.error(errorOrders);
  });
}, function(errorUser) {
  console.error(errorUser);
});
// 4 niveles de anidación, 4 funciones de error. Ilegible.

Callback hell en todo su esplendor

⭐ Por qué importa: El callback hell NO es un problema técnico: es un problema de LEGIBILIDAD. El código funciona, pero mantenerlo y debuggearlo es un infierno. Por eso nacieron las Promises y luego async/await.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

1.10.3 Promises: la primera solución elegante

Una Promise (promesa) es un OBJETO que representa un valor que ESTARÁ disponible en el futuro (o que NUNCA llegará). Tiene 3 estados: pending (esperando), fulfilled (cumplida, con un valor), rejected (rechazada, con un error). Se 'consume' con .then() para el éxito y .catch() para el error.

La anatomía de una Promise

// Crear una Promise
const miPromesa = new Promise((resolve, reject) => {
  setTimeout(() => {
    const exito = true;
    if (exito) {
      resolve('¡Listo!');  // se cumplió: pasa el valor al .then()
    } else {
      reject('Algo falló');  // se rechazó: pasa el error al .catch()
    }
  }, 2000);
});

// Consumir la Promise
miPromesa
  .then(resultado => console.log(resultado))   // '¡Listo!'
  .catch(error => console.error(error));       // si falló

Crear y consumir una Promise

Promise.all: ejecutar varias en paralelo

// Si tienes 3 peticiones independientes, ejecútalas EN PARALELO
const promesa1 = fetch('/api/usuarios');
const promesa2 = fetch('/api/productos');
const promesa3 = fetch('/api/pedidos');

Promise.all([promesa1, promesa2, promesa3])
  .then(respuestas => Promise.all(respuestas.map(r => r.json())))
  .then(([usuarios, productos, pedidos]) => {
    // Las 3 se completaron. Más rápido que esperar una por una.
    console.log({ usuarios, productos, pedidos });
  })
  .catch(error => console.error('Alguna falló:', error));

Promise.all: paralelismo

⭐ Rendimiento: Promise.all es FUNDAMENTAL: si tienes 5 peticiones independientes, esperarlas en serie tarda 5 segundos. Con Promise.all, tardan lo que tarde la MÁS LENTA (puede ser 1 segundo). 5 veces más rápido.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

1.10.4 async/await: código asíncrono legible

async/await (ES2017) es syntactic sugar sobre las Promises: te permite escribir código asíncrono que se LEE como código sincrónico. Es la forma MODERNA y la que verás en TODO el código nuevo. Si dominas async/await, dominas la asincronía de JavaScript.

El mismo ejemplo, con .then() vs async/await

// Con .then() (Promise clásico)
function cargarUsuario(id) {
  return fetch(`/api/usuarios/${id}`)
    .then(respuesta => respuesta.json())
    .then(usuario => {
      console.log(usuario);
      return usuario;
    })
    .catch(error => console.error(error));
}

// Con async/await (moderno) — MISMO RESULTADO, código más claro
async function cargarUsuario(id) {
  try {
    const respuesta = await fetch(`/api/usuarios/${id}`);
    const usuario = await respuesta.json();
    console.log(usuario);
    return usuario;
  } catch (error) {
    console.error(error);
  }
}

Promise.then() vs async/await

Las 3 reglas de oro de async/await

  • async: marca la función como asíncrona. Sin esto, await no funciona.
  • await: espera a que una Promise se resuelva. Solo se puede usar dentro de funciones async.
  • try/catch: para manejar errores, igual que en código síncrono. Reemplaza al .catch() de las Promises.
⭐ Detrás de cámaras: async/await no es magia: debajo sigue siendo una Promise. Lo que hace es darte una sintaxis más limpia. Si debuggearas con DevTools, verías las Promises debajo. Pero para el 99% del trabajo, async/await es lo que usarás.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

1.10.5 Fetch API: peticiones HTTP modernas

fetch() es la API nativa del navegador para hacer peticiones HTTP. Reemplazó al antiguo XMLHttpRequest (que era un infierno de callbacks y config). Con fetch + async/await, hacer una petición a un servidor se reduce a 3 líneas.

GET: pedir datos al servidor

async function obtenerUsuarios() {
  const respuesta = await fetch('/api/usuarios');
  const usuarios = await respuesta.json();  // convierte JSON a objeto JS
  return usuarios;
}

// Uso
const usuarios = await obtenerUsuarios();
console.log(usuarios);

GET con fetch

POST: enviar datos al servidor

async function crearUsuario(nuevoUsuario) {
  const respuesta = await fetch('/api/usuarios', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(nuevoUsuario)  // convierte objeto JS a JSON
  });
  const usuarioCreado = await respuesta.json();
  return usuarioCreado;
}

// Uso
const nuevo = await crearUsuario({ nombre: 'Ana', email: 'ana@mail.com' });

POST con fetch

Verbo HTTPPara qué sirveCuerpo de la petición
GETPedir datos.No tiene.
POSTCrear un recurso nuevo.Sí, con los datos.
PUT / PATCHActualizar un recurso existente.Sí, con los datos nuevos.
DELETEEliminar un recurso.No tiene.
⭐ CRUD = verbos HTTP: El ciclo CRUD (Create, Read, Update, Delete) se mapea directamente a los verbos HTTP: POST, GET, PUT/PATCH, DELETE. Si entiendes este mapeo, entiendes el 80% de las APIs REST.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

1.10.6 Manejo de errores: try/catch y .catch()

Las cosas fallan. La red se cae. El servidor se desconecta. El JSON viene malformado. El usuario pierde conexión a mitad de una petición. Un buen código NO IGNORA estos casos: los anticipa, los maneja, y le da feedback útil al usuario.

try/catch con async/await

async function cargarDatos() {
  try {
    const respuesta = await fetch('/api/datos');
    if (!respuesta.ok) {  // fetch no lanza error con 404, hay que chequearlo
      throw new Error(`HTTP ${respuesta.status}: ${respuesta.statusText}`);
    }
    const datos = await respuesta.json();
    return datos;
  } catch (error) {
    // Mostrar mensaje útil al usuario
    mostrarError('No pude cargar los datos. Revisa tu conexión.');
    console.error('Detalle técnico:', error);
    return null;  // o lo que tu app necesite
  }
}

Manejo robusto de errores

Errores comunes con fetch

ErrorCausaCómo manejarlo
Failed to fetchRed caída, CORS, servidor apagado.try/catch y mensaje al usuario.
404 Not FoundLa URL no existe.Chequear respuesta.ok y mostrar 'no encontrado'.
500 Internal Server ErrorBug en el servidor.Log del error y mensaje genérico al usuario.
SyntaxError: Unexpected tokenEl servidor no devolvió JSON válido.Chequear Content-Type antes de hacer .json().
⭐ Trampa común: fetch SOLO lanza error si la red falla. Un 404 o 500 NO lanza error: la petición se 'completó' con un código de error. SIEMPRE chequea respuesta.ok antes de procesar. Es el error #1 de los principiantes.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

1.10.7 Frameworks JS: React, Vue, Angular y Svelte en el horizonte

Hasta ahora escribiste JavaScript 'puro' (vanilla): manipulación directa del DOM, fetch, async/await, eventos. Funciona, pero cuando tu app crece (más de 5 vistas, estado compartido entre componentes, listas grandes, formularios complejos), el código se vuelve difícil de mantener. Aquí entran los FRAMEWORKS JS: librerías que te dan estructura, reactividad, y patrones probados para apps complejas. Los 4 gigantes son React (Meta), Vue (Evan You), Angular (Google) y Svelte (Rich Harris). Cada uno tiene filosofía distinta, comunidad distinta, y casos de uso ideales. Aquí vas a entender el panorama para saber cuál aprender primero cuando termines este curso.

📷 Imagen referencial: Los 4 frameworks JS más usados: React (Meta, azul), Vue (verde,渐进), Angular (Google, rojo, opinionated), Svelte (naranja, compilado). Cada uno con su filosofía, curva de aprendizaje, y casos de uso ideales.

Los 4 frameworks JS más usados en 2025: comparativa honesta

FrameworkCreadorAñoCurvaTrabajoIdeal para
ReactMeta (Facebook)2013MediaMuy alta (60% ofertas junior)Apps de todo tipo. La opción #1 para找工作. Ecosistema gigante.
VueEvan You (ex-Google)2014BajaMedia-Alta (popular en Asia, Europa)Proyectos渐进, MVPs, equipos que vienen de jQuery. Sintaxis más simple.
AngularGoogle2016AltaAlta (enterprise, bancos, gobierno)Apps enterprise grandes, equipos grandes, donde la consistencia es clave.
SvelteRich Harris2016BajaMedia (creciendo rápido)Apps pequeñas/medianas donde el rendimiento importa. Compilador, no runtime.

El MISMO componente 'Contador' en los 4 frameworks

// === REACT (con useState hook) ===
import { useState } from 'react';

function Contador() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Contador: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}
// Filosofia: estado centralizado en el componente, re-render cuando cambia.

// === VUE 3 (Composition API con <script setup>) ===
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>

<template>
  <div>
    <p>Contador: {{ count }}</p>
    <button @click="count++">+1</button>
  </div>
</template>
// Filosofia: reactividad declarativa, HTML extendido. Familiar para gente de HTML/jQuery.

// === ANGULAR (con TypeScript y decoradores) ===
import { Component } from '@angular/core';

@Component({
  selector: 'app-contador',
  template: `
    <div>
      <p>Contador: {{ count }}</p>
      <button (click)="increment()">+1</button>
    </div>
  `
})
export class ContadorComponent {
  count = 0;
  increment() { this.count++; }
}
// Filosofia: 'baterias incluidas'. TypeScript obligatorio, opinionated, estructura rigida.

// === SVELTE 4 (compilado, no runtime) ===
<script>
  let count = 0;
  function increment() { count++; }
</script>

<div>
  <p>Contador: {count}</p>
  <button on:click={increment}>+1</button>
</div>
// Filosofia: el compilador HACE el trabajo. Sin virtual DOM, sin runtime, código minimo.

El mismo 'Contador' en React, Vue, Angular y Svelte

Las preguntas clave para elegir framework

  • ¿Qué pide el mercado laboral de tu ciudad/país? React domina en USA/Europa, Vue es muy fuerte en China/Asia, Angular en enterprise europeo. Busca en LinkedIn 'React junior' vs 'Vue junior' vs 'Angular junior' y compara.
  • ¿Tu equipo viene de qué background? De jQuery/HTML → Vue es el camino más natural. De Java/C# → Angular se siente familiar (TypeScript, decoradores, DI). De Ruby/Python → React (JS flexible, menos estructura).
  • ¿Qué tipo de app vas a construir? Un SaaS B2B con 50 vistas → React o Angular (estructura). Una landing page interactiva → Svelte (performance). Un MVP rápido → Vue (curva baja). Un dashboard interno → React.
  • ¿Cuánto tiempo tienes para aprender? React: 2-3 meses para ser productivo. Vue: 1 mes. Svelte: 2 semanas. Angular: 3-4 meses (TypeScript + decoradores + RxJS).
  • ¿Quieres el camino más popular o el más moderno? React es el más popular (más ofertas, más recursos, más librerías). Svelte es el más moderno (mejor DX, mejor performance, menos código).

Cómo instalar cada framework (Vite es el estándar en 2025)

# REACT (recomendado con Vite)
npm create vite@latest mi-app -- --template react-ts
cd mi-app
npm install
npm run dev  # http://localhost:5173

# VUE 3 (oficial con create-vue)
npm create vue@latest mi-app
cd mi-app
npm install
npm run dev  # http://localhost:5173

# ANGULAR (oficial con Angular CLI, requiere Node 18+)
npm install -g @angular/cli
ng new mi-app --routing --style=scss
cd mi-app
ng serve  # http://localhost:4200

# SVELTE 4 / SVELTEKIT (oficial con create-svelte)
npm create svelte@latest mi-app
cd mi-app
npm install
npm run dev  # http://localhost:5173

# Tiempo de setup: <5 minutos en todos. Vite es el estándar,
# arranca en 1 segundo, hace HMR instantaneo.

# Estructura de cada proyecto:
# React/Vue/Svelte: src/App.{jsx,vue,svelte}, src/main.{jsx,ts}, src/index.css
# Angular: src/app/, src/app/app.component.ts, src/main.ts

Comando de instalación de los 4 frameworks (todos con Vite)

⭐ La base importa más que el framework: Para tu carrera junior, la elección importa MENOS de lo que crees. Si aprendes JavaScript moderno, DOM, async/await (este tema), HTML y CSS bien, migrar entre React/Vue/Svelte te toma 1-2 semanas. La base es la misma. La excepción: si quieres trabajar en Google/enterprise → aprende Angular. Si quieres el camino más popular y flexible → React. Si quieres la curva más suave y渐进 → Vue. Si quieres lo más moderno y quieres destacar → Svelte. En este curso usamos React porque es el más demandado, pero al terminar puedes migrar a cualquiera en 2 semanas. La Fundación es lo que importa, no la herramienta.
🎬
Video del instructor

El administrador aún no ha insertado un video para esta sección.

📚 Contenido ampliado

Material adicional, referencias externas verificadas y ejemplos extendidos.

🤖 AI Mission

Asincronía se entiende haciendo peticiones reales. La IA explica, tú experimentas.

Misión: Construye un mini-buscador de películas usando la API pública de OMDB (o JSONPlaceholder). Escribe el fetch + async/await a mano, maneja errores con try/catch, muestra loading mientras carga, y los resultados en pantalla. Pídele a la IA que revise tu código y te sugiera mejoras. Anota en tu cuaderno: ¿cuántas veces tuviste que esperar a una petición real para entender el flujo?

Pasos sugeridos

  1. Abre VS Code. Crea un index.html con un <input> para búsqueda y un <button>.
  2. Crea app.js. Agrega un listener al form: al hacer submit, lee el valor del input.
  3. Llama a fetch('https://www.omdbapi.com/?s=' + busqueda + '&apikey=TU_KEY') o usa JSONPlaceholder.
  4. Muestra 'Buscando...' mientras carga (estado loading).
  5. Convierte la respuesta con await respuesta.json().
  6. Renderiza los resultados en una <ul> con map + template literals.
  7. Agrega try/catch: si falla, muestra 'No se encontraron resultados' o 'Error de red'.
  8. Prueba con 3 búsquedas reales: una que exista, una que no exista, una con la red apagada.
  9. Pídele a la IA: 'Tengo este buscador con fetch. Sugiere 2 mejoras: loading state, manejo de errores, accesibilidad. NO me des código, dime la técnica y por qué.'
  10. Anota en tu cuaderno, bajo 'Asincronía en la práctica': québugs tuviste, qué entendiste al VER la petición real que la IA no te podría haber enseñado.

📓 Entregable: Capturas del buscador funcionando (búsqueda exitosa, sin resultados, error de red), código de app.js con try/catch, y media página de cuaderno reflexionando sobre asincronía.

🚫 Errores típicos de razonamiento

Error 1: Olvidar await y obtener una Promise en vez del valor.
Por qué: Si escribes const datos = fetch('/api'), obtienes una Promise, no los datos. fetch es asíncrono: hay que esperar con await. Olvidar await es el error #1 de principiantes con async/await. Si ves 'Promise { <pending> }' en tu console.log, te faltó el await.
Error 2: No chequear respuesta.ok después de fetch y obtener un 404 silencioso.
Por qué: fetch SOLO rechaza la Promise si la RED falla (no hay internet, CORS, DNS). Si el servidor responde con 404 o 500, fetch lo considera 'éxito' porque la petición HTTP se completó. Hay que chequear respuesta.ok manualmente. Si no, tu código intenta procesar HTML de error como si fuera JSON y explota.
Error 3: Usar await dentro de un map() o forEach() (que NO esperan).
Por qué: Si haces lista.map(async item => await procesar(item)), el map NO espera a las Promises internas. Devuelve un array de Promises, no de valores. Solución: usa Promise.all(lista.map(...)) o un for...of (que sí espera). El forEach tampoco espera, ojo.
Error 4: Encadenar .then() en vez de usar async/await en código nuevo.
Por qué: .then() funciona, pero async/await es más legible y más fácil de debuggear. En 2025, async/await es el estándar. Si ves tutoriales con cadenas largas de .then(), probablemente son de antes de 2017. Aprende async/await primero; los .then() los entenderás solos si los necesitas.
Error 5: Olvidar try/catch y que un error 'no atrapado' rompa toda la app.
Por qué: Si una función async lanza un error y no hay try/catch, el error se propaga y puede romper TODA la app. En producción, un solo error de red no controlado puede dejar tu página en blanco. Regla: SIEMPRE try/catch en funciones async que hagan fetch, y siempre ten un plan para 'qué muestro al usuario si falla'.

🧪 Laboratorio práctico

Asincronía sin peticiones reales es teoría. Haz 10 peticiones y entenderás.

Laboratorio: App del clima con OpenWeatherMap (o API pública)

Objetivo: Crear una aplicación que pida el clima actual de una ciudad usando la API de OpenWeatherMap (gratis con registro) o cualquier API pública similar. Practicarás: fetch, async/await, try/catch, manejo de loading y errores, y renderizado dinámico.

Pasos

  1. Regístrate en OpenWeatherMap y obtén una API key gratuita.
  2. Crea clima.html con un <input> para ciudad y un <button>.
  3. Crea clima.js. Listener al form: al submit, prevén el default y lee la ciudad.
  4. Muestra 'Cargando...' mientras se hace la petición.
  5. fetch(`https://api.openweathermap.org/data/2.5/weather?q=${ciudad}&appid=${KEY}&units=metric&lang=es`).
  6. Chequea respuesta.ok. Si no, lanza error con mensaje claro.
  7. Extrae: nombre, temperatura, descripción, humedad, icono.
  8. Renderiza con template literals en un <div> con clase 'tarjeta-clima'.
  9. try/catch: si la ciudad no existe, muestra 'No encontré la ciudad'. Si falla la red, 'Revisa tu conexión'.
  10. Prueba con: una ciudad válida, una inválida, y con la red apagada.
  11. Estiliza con CSS: tarjeta centrada, temperatura grande, descripción debajo.
  12. Haz commit: 'feat: app del clima con fetch, async/await y manejo de errores'.

📓 Entregable: Capturas de: (1) clima cargado correctamente, (2) ciudad no encontrada, (3) error de red, (4) código de clima.js con try/catch, (5) commit en Git.

📓 Tu cuaderno: Anota pseudocódigo, diagramas, errores que encontraste y respuestas a "explica sin código". La escritura manual refuerza tu razonamiento. Tu profesor puede pedirte que subas fotos de páginas específicas.