🎯 Objetivo del tema
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).
Por qué JavaScript no puede simplemente 'esperar' y qué pasa cuando lo intenta.
La forma histórica (y por qué casi nadie la usa ya en código nuevo).
Un objeto que representa un valor que ESTARÁ disponible en el futuro.
La forma moderna. Tu código se lee como si fuera sincrónico pero NO bloquea la página.
Cómo pedirle datos a un servidor desde el navegador.
Qué hacer cuando algo falla: red caída, servidor caído, JSON inválido.
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ón | Por qué es asíncrona | Tiempo típico |
|---|---|---|
| Petición HTTP (fetch) | Viaja por la red hasta el servidor y de vuelta. | 50ms - 5s. |
| setTimeout / setInterval | Espera un tiempo antes de ejecutar. | Variable. |
| Lectura de archivos | Lee del disco duro o de la red. | 10ms - varios segundos. |
| Eventos del usuario | Espera a que el usuario interactúe. | Indefinido. |
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
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
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.
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 HTTP | Para qué sirve | Cuerpo de la petición |
|---|---|---|
| GET | Pedir datos. | No tiene. |
| POST | Crear un recurso nuevo. | Sí, con los datos. |
| PUT / PATCH | Actualizar un recurso existente. | Sí, con los datos nuevos. |
| DELETE | Eliminar un recurso. | No tiene. |
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
| Error | Causa | Cómo manejarlo |
|---|---|---|
| Failed to fetch | Red caída, CORS, servidor apagado. | try/catch y mensaje al usuario. |
| 404 Not Found | La URL no existe. | Chequear respuesta.ok y mostrar 'no encontrado'. |
| 500 Internal Server Error | Bug en el servidor. | Log del error y mensaje genérico al usuario. |
| SyntaxError: Unexpected token | El servidor no devolvió JSON válido. | Chequear Content-Type antes de hacer .json(). |
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.
Los 4 frameworks JS más usados en 2025: comparativa honesta
| Framework | Creador | Año | Curva | Trabajo | Ideal para |
|---|---|---|---|---|---|
| React | Meta (Facebook) | 2013 | Media | Muy alta (60% ofertas junior) | Apps de todo tipo. La opción #1 para找工作. Ecosistema gigante. |
| Vue | Evan You (ex-Google) | 2014 | Baja | Media-Alta (popular en Asia, Europa) | Proyectos渐进, MVPs, equipos que vienen de jQuery. Sintaxis más simple. |
| Angular | 2016 | Alta | Alta (enterprise, bancos, gobierno) | Apps enterprise grandes, equipos grandes, donde la consistencia es clave. | |
| Svelte | Rich Harris | 2016 | Baja | Media (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.tsComando de instalación de los 4 frameworks (todos con Vite)
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
- Abre VS Code. Crea un index.html con un <input> para búsqueda y un <button>.
- Crea app.js. Agrega un listener al form: al hacer submit, lee el valor del input.
- Llama a fetch('https://www.omdbapi.com/?s=' + busqueda + '&apikey=TU_KEY') o usa JSONPlaceholder.
- Muestra 'Buscando...' mientras carga (estado loading).
- Convierte la respuesta con await respuesta.json().
- Renderiza los resultados en una <ul> con map + template literals.
- Agrega try/catch: si falla, muestra 'No se encontraron resultados' o 'Error de red'.
- Prueba con 3 búsquedas reales: una que exista, una que no exista, una con la red apagada.
- 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é.'
- 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
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.
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.
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.
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.
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
- Regístrate en OpenWeatherMap y obtén una API key gratuita.
- Crea clima.html con un <input> para ciudad y un <button>.
- Crea clima.js. Listener al form: al submit, prevén el default y lee la ciudad.
- Muestra 'Cargando...' mientras se hace la petición.
- fetch(`https://api.openweathermap.org/data/2.5/weather?q=${ciudad}&appid=${KEY}&units=metric&lang=es`).
- Chequea respuesta.ok. Si no, lanza error con mensaje claro.
- Extrae: nombre, temperatura, descripción, humedad, icono.
- Renderiza con template literals en un <div> con clase 'tarjeta-clima'.
- try/catch: si la ciudad no existe, muestra 'No encontré la ciudad'. Si falla la red, 'Revisa tu conexión'.
- Prueba con: una ciudad válida, una inválida, y con la red apagada.
- Estiliza con CSS: tarjeta centrada, temperatura grande, descripción debajo.
- 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.