Volver al inicio
Lección 14

Fetch API y async/await

Aprende la forma moderna de hacer peticiones HTTP y manejar código asíncrono de manera elegante con async/await.

1. Fetch API - La forma moderna

Fetch API es la forma moderna de hacer peticiones HTTP. Es mucho más simple y usa Promesas.

Ejemplo básico GET:

fetch-basico.jsjavascript
1// Con Fetch es mucho más simple
2fetch('https://jsonplaceholder.typicode.com/users/1')
3 .then(response => response.json())
4 .then(datos => {
5 console.log('Usuario:', datos);
6 })
7 .catch(error => {
8 console.log('Error:', error);
9 });

Ventajas de Fetch:

  • Sintaxis mucho más simple y limpia
  • Usa Promesas (se puede encadenar con .then)
  • Compatible con async/await
  • Más fácil manejar errores

2. ¿Qué son las Promesas?

Una Promesa es un objeto que representa una operación que todavía no ha terminado, pero que terminará en el futuro.

Puede tener 3 estados:

Pending

Esperando (aún no terminó)

Fulfilled

Completada con éxito

Rejected

Falló (error)

promesas.jsjavascript
1// Fetch devuelve una Promesa
2const promesa = fetch('https://jsonplaceholder.typicode.com/users/1');
3
4console.log(promesa); // Promise {<pending>}
5
6// Usamos .then() para cuando se complete
7promesa
8 .then(response => response.json())
9 .then(datos => {
10 console.log('✅ Datos recibidos:', datos);
11 })
12 .catch(error => {
13 console.log('❌ Error:', error);
14 });

3. async/await - Código más limpio

async/await es una forma más moderna de trabajar con Promesas. Hace que el código asíncrono se vea como código síncrono.

Sin async/await (con .then):

sin-async.jsjavascript
1fetch('https://jsonplaceholder.typicode.com/users/1')
2 .then(response => response.json())
3 .then(datos => {
4 console.log('Usuario:', datos);
5 })
6 .catch(error => {
7 console.log('Error:', error);
8 });

Con async/await (más limpio):

con-async.jsjavascript
1async function obtenerUsuario() {
2 try {
3 const response = await fetch('https://jsonplaceholder.typicode.com/users/1');
4 const datos = await response.json();
5 console.log('Usuario:', datos);
6 } catch (error) {
7 console.log('Error:', error);
8 }
9}
10
11obtenerUsuario();

Reglas de async/await:

  • async se pone antes de la función
  • await solo funciona dentro de funciones async
  • await espera a que la Promesa se complete
  • Usa try/catch para manejar errores

4. Enviar datos (POST)

Para enviar datos al servidor usamos el método POST con opciones adicionales:

fetch-post.jsjavascript
1async function crearUsuario() {
2 try {
3 const nuevoUsuario = {
4 name: 'Ana García',
5 email: 'ana@example.com'
6 };
7
8 const response = await fetch('https://jsonplaceholder.typicode.com/users', {
9 method: 'POST',
10 headers: {
11 'Content-Type': 'application/json'
12 },
13 body: JSON.stringify(nuevoUsuario)
14 });
15
16 const datos = await response.json();
17 console.log('Usuario creado:', datos);
18 } catch (error) {
19 console.log('Error:', error);
20 }
21}
22
23crearUsuario();

5. Múltiples peticiones

Una después de otra (secuencial):

secuencial.jsjavascript
1async function obtenerDatos() {
2 try {
3 // Primero obtener el usuario
4 const respuestaUsuario = await fetch('https://jsonplaceholder.typicode.com/users/1');
5 const usuario = await respuestaUsuario.json();
6 console.log('Usuario:', usuario.name);
7
8 // Luego obtener sus posts
9 const respuestaPosts = await fetch('https://jsonplaceholder.typicode.com/users/1/posts');
10 const posts = await respuestaPosts.json();
11 console.log('Posts:', posts.length);
12 } catch (error) {
13 console.log('Error:', error);
14 }
15}
16
17obtenerDatos();

Todas al mismo tiempo (paralelo):

paralelo.jsjavascript
1async function obtenerTodo() {
2 try {
3 // Lanzar todas las peticiones al mismo tiempo
4 const [respuestaUsuario, respuestaPosts, respuestaTodos] = await Promise.all([
5 fetch('https://jsonplaceholder.typicode.com/users/1'),
6 fetch('https://jsonplaceholder.typicode.com/posts?userId=1'),
7 fetch('https://jsonplaceholder.typicode.com/todos?userId=1')
8 ]);
9
10 const usuario = await respuestaUsuario.json();
11 const posts = await respuestaPosts.json();
12 const todos = await respuestaTodos.json();
13
14 console.log('Usuario:', usuario.name);
15 console.log('Posts:', posts.length);
16 console.log('Todos:', todos.length);
17 } catch (error) {
18 console.log('Error:', error);
19 }
20}
21
22obtenerTodo();

Tip: Usa Promise.all() cuando las peticiones no dependan una de otra. Será mucho más rápido.

6. XMLHttpRequest vs Fetch vs async/await

XMLHttpRequest

  • • Muy verboso
  • • Callbacks anidados
  • • Difícil de leer
  • • Forma antigua

Fetch + .then

  • • Más simple
  • • Usa Promesas
  • • Puede anidar .then
  • • Mejor que XHR

async/await

  • • Muy limpio
  • • Fácil de leer
  • • Código lineal
  • • La mejor opción

Ejercicio práctico

Galería de Usuarios con Fetch y async/await

Vas a crear una aplicación web que muestre información de usuarios y sus publicaciones. Practicarás async/await para obtener datos de una API y manipulación del DOM para crear la interfaz dinámica.

1 Crear la estructura HTML

Crea un archivo index.html con esta estructura básica:

  • Un título h1 que diga "Galería de Usuarios"
  • Un botón con id cargar-btn y texto "Cargar Usuarios"
  • Un div contenedor con id usuarios-container donde aparecerán las tarjetas
  • Un tag script que importe el archivo app.js antes del cierre del body

Consejo: Puedes usar Bootstrap para estilizar las tarjetas fácilmente.

Agrega el CDN de Bootstrap en el head de tu HTML y usa clases como card, btn btn-primary, container, etc.

📚 Ver documentación de Bootstrap

2 Crear la función para obtener datos (async/await)

En app.js, crea una función async llamada cargarUsuarios():

🌐 API recomendada: DummyJSON

Una API gratuita y confiable para pruebas y prototipos

Obtener UN usuario específico:

https://dummyjson.com/users/1

→ Datos en: data.firstName, data.lastName, etc.

Obtener MÚLTIPLES usuarios (con límite):

https://dummyjson.com/users?limit=3

→ Datos en: data.users (es un array)

⚠️ Cambia limit=3 por el número que necesites (ej: limit=15 para 15 usuarios)

Posts de un usuario específico:

https://dummyjson.com/posts/user/1

→ Datos en: data.posts (es un array)

⚠️ Reemplaza el 1 por el ID del usuario

💡 Ejemplo rápido: Obtener un usuario y mostrar su nombre

ejemplo-dummyjson.jsjavascript
1async function ejemploRapido() {
2 const response = await fetch('https://dummyjson.com/users/1');
3 const data = await response.json();
4
5 // Los datos del usuario están directamente en 'data'
6 const nombreCompleto = data.firstName + ' ' + data.lastName;
7
8 // Crear y agregar un h3 al DOM
9 const titulo = document.createElement('h3');
10 titulo.textContent = nombreCompleto;
11 document.body.appendChild(titulo);
12}

2.1 Obtener usuarios

  • Usa await fetch() para obtener datos de:
    https://dummyjson.com/users?limit=3
  • Convierte la respuesta a JSON con await response.json()
  • Los datos vienen en data.users (DummyJSON usa esta estructura)

2.2 Obtener posts de cada usuario

  • Para cada usuario, obtén sus posts de:
    https://dummyjson.com/posts/user/1
    (reemplaza el 1 con el id del usuario)
  • Usa Promise.all() para hacer todas las peticiones en paralelo
  • Los posts vienen en data.posts

2.3 Manejo de errores

  • Envuelve todo el código en un bloque try/catch
  • Si hay error, muestra un mensaje en consola con console.error()

⚠️ API alternativa (si DummyJSON no funciona):

Puedes usar Dog API para mostrar razas de perros e imágenes:

  • • Lista de razas: https://dog.ceo/api/breeds/list/all
  • • Imagen aleatoria de una raza: https://dog.ceo/api/breed/shiba/images/random
  • • Múltiples imágenes: https://dog.ceo/api/breed/labrador/images/random/3

(Reemplaza "shiba" o "labrador" con cualquier raza)

3 Crear las tarjetas dinámicamente (Interfaz)

Dentro de la función cargarUsuarios(), después de obtener los datos:

3.1 Limpiar el contenedor

  • Obtén el contenedor con document.getElementById('usuarios-container')
  • Limpia su contenido con container.innerHTML = ''

3.2 Crear una tarjeta para cada usuario

  • Recorre el array de usuarios con forEach
  • Para cada usuario, crea un div con document.createElement('div')
  • Agrega una clase CSS a la tarjeta (ejemplo: 'usuario-card')

3.3 Agregar contenido a cada tarjeta

Usa innerHTML para agregar el HTML de la tarjeta. Debe mostrar:

  • Nombre del usuario en un h2 o h3 (usa usuario.firstName y usuario.lastName)
  • Email en un párrafo (usuario.email)
  • Cantidad de posts (usa posts.length)
  • Títulos de los primeros 3 posts en divs o en una lista (usa posts.slice(0, 3) y post.title)

3.4 Agregar la tarjeta al contenedor

  • Usa container.appendChild(card) para agregar cada tarjeta

4 Conectar el botón con la función

  • Al final de app.js, obtén el botón con document.getElementById('cargar-btn')
  • Agrega un event listener con addEventListener('click', cargarUsuarios)
  • ¡Prueba tu aplicación! Haz clic en el botón y deberían aparecer las tarjetas

Tip: Usa concatenación de strings o template literals para construir el HTML dentro de innerHTML

Extra: Puedes agregar un mensaje de "Cargando..." mientras se obtienen los datos

Resumen

Fetch API es la forma moderna de hacer peticiones HTTP
Promesas representan operaciones asíncronas (pending, fulfilled, rejected)
async/await hace el código asíncrono más limpio y fácil de leer
Usa try/catch para manejar errores con async/await
Promise.all() ejecuta múltiples peticiones en paralelo
async/await es la mejor forma de trabajar con código asíncrono en JavaScript moderno