JavaScript asíncrono: Promises, async/await, fetch y APIs

Aprendé JavaScript asíncrono con Promises, async/await, fetch, manejo de errores y consumo de APIs.


Muchas tareas no terminan inmediatamente: una petición HTTP, un temporizador o una lectura externa pueden requerir esperar.

setTimeout

setTimeout() programa una función para ejecutarse después de un tiempo. No detiene el resto del programa mientras espera.

console.log("Inicio");

setTimeout(() => {
    console.log("Pasaron dos segundos");
}, 2000);

console.log("Fin");

El programa no bloquea toda la ejecución esperando el temporizador.

Qué es una Promise

Una Promise representa el resultado futuro de una operación. Puede estar pendiente, resolverse correctamente o rechazarse por un error.

Una Promise representa un resultado que puede estar pendiente, completarse correctamente o fallar.

pending
fulfilled
rejected

Ejemplo de Promise

const promesa = new Promise((resolve, reject) => {
    const correcto = true;

    if (correcto) {
        resolve("Operación completada");
    } else {
        reject(new Error("Ocurrió un error"));
    }
});

promesa
    .then(resultado => console.log(resultado))
    .catch(error => console.error(error));

async y await

async marca una función como asíncrona y await permite esperar una Promise con una sintaxis más parecida al código secuencial.

async function obtenerDatos() {
    const resultado = await Promise.resolve("Datos recibidos");

    console.log(resultado);
}

obtenerDatos();

await solo puede utilizarse dentro de una función async o en contextos de módulos que permitan top-level await.

fetch

fetch() realiza una petición HTTP y devuelve una Promise. Después debemos leer el cuerpo de la respuesta, por ejemplo con response.json().

fetch() permite realizar peticiones HTTP desde el navegador.

async function cargarUsuarios() {
    const respuesta = await fetch("https://jsonplaceholder.typicode.com/users");

    const usuarios = await respuesta.json();

    console.log(usuarios);
}

cargarUsuarios();

Comprobar el estado HTTP

fetch() no rechaza automáticamente una Promise por respuestas como 404 o 500. Por eso comprobamos response.ok o el código de estado.

async function cargarUsuarios() {
    const respuesta = await fetch("https://jsonplaceholder.typicode.com/users");

    if (!respuesta.ok) {
        throw new Error(`HTTP ${respuesta.status}`);
    }

    return respuesta.json();
}

try…catch

try...catch permite manejar errores sin interrumpir abruptamente la aplicación. Dentro de catch podemos informar el problema o mostrar una alternativa al usuario.

async function iniciar() {
    try {
        const usuarios = await cargarUsuarios();
        console.log(usuarios);
    } catch (error) {
        console.error("No se pudieron cargar los usuarios", error);
    }
}

iniciar();

Mostrar datos en el DOM

<ul id="usuarios"></ul>
async function mostrarUsuarios() {
    const lista = document.querySelector("#usuarios");

    try {
        const respuesta = await fetch(
            "https://jsonplaceholder.typicode.com/users"
        );

        if (!respuesta.ok) {
            throw new Error("Error HTTP");
        }

        const usuarios = await respuesta.json();

        usuarios.forEach(usuario => {
            const item = document.createElement("li");
            item.textContent = usuario.name;
            lista.append(item);
        });
    } catch (error) {
        lista.textContent = "No se pudieron cargar los datos";
    }
}

mostrarUsuarios();

GET y POST: dos métodos HTTP fundamentales

GET y POST son métodos del protocolo HTTP. No son funciones propias de JavaScript: indican qué tipo de operación queremos realizar sobre un recurso de una API.

GET: obtener información

Usamos GET principalmente para consultar datos. Una petición GET normalmente no debería modificar información en el servidor.

Con fetch(), GET es el método por defecto, por eso no hace falta indicarlo explícitamente:

const respuesta = await fetch("/api/tareas");

const tareas = await respuesta.json();

console.log(tareas);

También podemos enviar parámetros en la URL. Por ejemplo, para pedir únicamente tareas completadas:

const respuesta = await fetch(
    "/api/tareas?completada=true"
);

Esos datos viajan en la URL y suelen utilizarse para filtros, búsquedas, paginación u otras opciones de consulta.

POST: enviar información

Usamos POST normalmente para crear o enviar datos al servidor. A diferencia de GET, los datos suelen viajar en el cuerpo de la petición.

const respuesta = await fetch("/api/tareas", {
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify({
        titulo: "Practicar JavaScript"
    })
});

const tareaCreada = await respuesta.json();

console.log(tareaCreada);

En este ejemplo:

  • method: "POST" indica que queremos enviar información;
  • Content-Type: application/json informa al servidor que el cuerpo contiene JSON;
  • JSON.stringify() convierte el objeto de JavaScript a texto JSON;
  • response.json() convierte la respuesta JSON del servidor nuevamente en un valor JavaScript.

GET o POST: ¿cuál usar?

GET  → consultar información
POST → enviar o crear información

Por ejemplo, listar tareas sería normalmente un GET, mientras que crear una nueva tarea sería un POST.

Una API no siempre es pública

Algunas APIs necesitan autenticación, claves, permisos o restricciones CORS. No debemos exponer secretos privados dentro del JavaScript que se ejecuta en el navegador.

Promise.all

Promise.all() espera varias Promises en paralelo y devuelve sus resultados juntos. Es útil cuando las operaciones no dependen unas de otras.

const [usuarios, publicaciones] = await Promise.all([
    fetch("/api/usuarios").then(r => r.json()),
    fetch("/api/publicaciones").then(r => r.json())
]);

Ejercicio

Consumí una API pública de prueba, mostrale al usuario un mensaje de “Cargando…”, renderizá los resultados y manejá un posible error.

Errores comunes

  • olvidar await;
  • suponer que fetch rechaza automáticamente cualquier HTTP 404 o 500;
  • no usar try...catch;
  • exponer claves privadas en el frontend;
  • intentar consumir una API bloqueada por CORS sin entender el origen del problema.

¿Te sirvió esta guía? ☕

Si este contenido te ayudó a aprender JavaScript, podés apoyar a Club Programador. Cada aporte ayuda a mantener el sitio online y a seguir publicando material gratuito.

🇦🇷 Apoyar desde Argentina

☕ Invitame un café con Mercado Pago

🌎 Apoyar desde otro país

☕ Apoyar con PayPal

Seguí aprendiendo JavaScript

← Eventos y formularios en JavaScript: click, input, submit y validaciones

Proyecto final JavaScript: aplicación de tareas con DOM, eventos y localStorage →


Descubre más desde Club Programador

Suscríbete y recibe las últimas entradas en tu correo electrónico.

2 opiniones en “JavaScript asíncrono: Promises, async/await, fetch y APIs”

Deja un comentario

Descubre más desde Club Programador

Suscríbete ahora para seguir leyendo y obtener acceso al archivo completo.

Seguir leyendo