Peticiones con async/await y Fetch API
Aprende el estándar moderno de JavaScript para consumir servicios web y APIs REST: la sintaxis limpia de async y await junto con la API nativa fetch.
¿Qué son async y await?
Introducidas en ES2017, las palabras clave async y await son azúcar sintáctico sobre las Promesas. Permiten escribir código asíncrono con una estructura visual lineal y legible, idéntica al código síncrono tradicional.
async: Se coloca antes de una función para indicar que siempre retornará una Promesa.await: Solo puede usarse dentro de funcionesasync. Pausa la ejecución de la función hasta que la Promesa se resuelva, retornando su valor directamente.
Consumo de APIs con fetch()
La función global fetch() reemplazó al antiguo XMLHttpRequest para realizar peticiones HTTP (GET, POST, PUT, DELETE):
async function obtenerUsuarios() {
try {
const respuesta = await fetch("https://api.ejemplo.com/usuarios");
// Verificar si el estado HTTP está entre 200 y 299
if (!respuesta.ok) {
throw new Error(`Error en el servidor: Código ${respuesta.status}`);
}
// Convertir el cuerpo de la respuesta a JSON
const datos = await respuesta.json();
console.log("Usuarios recibidos:", datos);
} catch (error) {
console.error("Error al consultar la API:", error.message);
}
}
Peticiones POST para Enviar Datos
async function registrarEstudiante(nuevoEstudiante) {
const respuesta = await fetch("https://api.ejemplo.com/estudiantes", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(nuevoEstudiante)
});
return await respuesta.json();
}
⚡ Cliente de API con Fetch y Async/Await
Consulta datos remotos en formato JSON desde una API pública real y renderízalos dinámicamente:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Fetch API con Async/Await</title>
<style>
body { font-family: Arial, Helvetica, sans-serif; padding: 25px; background: #f8fafc; }
.card-api { max-width: 540px; background: white; border: 1px solid #cbd5e1; border-radius: 8px; padding: 22px; }
.barra-accion { display: flex; gap: 8px; margin-bottom: 15px; }
button { padding: 9px 16px; background: #0284c7; color: white; border: none; border-radius: 6px; font-weight: bold; cursor: pointer; }
button:hover { background: #0369a1; }
button:disabled { opacity: 0.6; cursor: not-allowed; }
.indicador { padding: 8px 12px; border-radius: 6px; font-size: 0.85rem; margin-bottom: 12px; }
.cargando { background: #e0f2fe; color: #0369a1; }
.error { background: #fee2e2; color: #991b1b; }
.lista-usuarios { list-style: none; padding: 0; margin: 0; }
.item-usuario { padding: 10px 12px; border-bottom: 1px solid #e2e8f0; display: flex; justify-content: space-between; align-items: center; }
.item-usuario:last-child { border-bottom: none; }
.email-tag { font-size: 0.8rem; color: #64748b; font-family: monospace; }
</style>
</head>
<body>
<div class="card-api">
<h3 style="margin-top: 0; color: #0f172a;">Directorio de Usuarios Externo</h3>
<div class="barra-accion">
<button id="btn-cargar" onclick="cargarUsuarios()">Consultar API Externa (JSONPlaceholder)</button>
</div>
<div id="caja-estado"></div>
<ul class="lista-usuarios" id="lista-usuarios"></ul>
</div>
<script>
async function cargarUsuarios() {
const btn = document.getElementById('btn-cargar');
const estado = document.getElementById('caja-estado');
const lista = document.getElementById('lista-usuarios');
btn.disabled = true;
lista.innerHTML = "";
estado.className = "indicador cargando";
estado.textContent = "⏳ Conectando con servidor remoto vía fetch()...";
try {
// Petición asíncrona real con fetch y await
const respuesta = await fetch('https://jsonplaceholder.typicode.com/users?_limit=4');
if (!respuesta.ok) {
throw new Error(`Código de estado HTTP: ${respuesta.status}`);
}
const usuarios = await respuesta.json();
estado.className = "indicador";
estado.style.background = "#dcfce7";
estado.style.color = "#166534";
estado.textContent = `✓ ${usuarios.length} usuarios recibidos correctamente.`;
// Renderizado en el DOM
lista.innerHTML = usuarios.map(u => `
<li class="item-usuario">
<div>
<strong>${u.name}</strong><br>
<span class="email-tag">${u.email}</span>
</div>
<span style="font-size: 0.75rem; background: #f1f5f9; padding: 3px 8px; border-radius: 4px;">ID #${u.id}</span>
</li>
`).join('');
} catch (error) {
estado.className = "indicador error";
estado.textContent = `✕ Error en la petición: ${error.message}`;
} finally {
btn.disabled = false;
}
}
</script>
</body>
</html>
¿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.