Promises

Semestre 1, 2025

Introducción

JavaScript es un lenguaje asíncrono y no bloqueante.

Ejemplo de código bloqueante:


console.log("Inicio");
alert("Bloqueo del código");
console.log("Fin");

¿Qué es la asincronía?

La asincronía permite ejecutar código sin bloquear la ejecución de otras tareas.

Ejemplo de asincronía en la vida real: Mientras esperas una pizza en un restaurante, puedes hacer otras cosas sin quedarte inmóvil.

En JavaScript, esto se maneja con:

  • Callbacks
  • Promesas
  • Async/Await

El manejo incorrecto de la asincronía puede afectar el rendimiento y la experiencia del usuario.

Promise API

Una Promesa representa el resultado eventual de una operación asíncrona.

Estructura de javascript que posee un estado y un resultado.

Estados de una promesa:

  • Pending (⏳ Pendiente)
  • Fulfilled (✅ Completada)
  • Rejected (❌ Rechazada)

Fetch

Fetch permite realizar peticiones HTTP de manera asíncrona.

✅ Devuelve una Promesa.

Ejemplo básico de `fetch`


fetch('https://pokeapi.co/api/v2/pokemon/')
    .then(response => response.json())
    .then(data => console.log("Datos obtenidos:", data.results))
    .catch(error => console.error("Error en la petición:", error));

Manejo de respuestas HTTP

Podemos verificar si una petición fue exitosa con `response.ok`.


fetch('https://pokeapi.co/api/v2/pokemon/')
    .then(response => {
        if (!response.ok) {
            throw new Error(`Error HTTP: ${response.status}`);
        }
        return response.json();
    })
    .then(data => console.log("Datos obtenidos:", data.results))
    .catch(error => console.error("Error en la petición:", error));

Realizando una petición POST

Podemos enviar datos a una API utilizando `fetch` con `POST`.


fetch('https://api.example.com/data', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({ nombre: 'Juan', edad: 25 })
})
.then(response => response.json())
.then(data => console.log("Respuesta del servidor:", data))
.catch(error => console.error("Error en la petición:", error));

Ejemplo


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

    if (exito) {
        resolve("Operación exitosa");
    } else {
        reject("Ocurrió un error");
    }
});

promesa.then(console.log).catch(console.error);
                        
function obtenerPokemones() {
    return new Promise((resolve, reject) => {
        fetch('https://pokeapi.co/api/v2/pokemon/')
            .then(response => {
                if (!response.ok) {
                    throw new Error(`Error HTTP: ${response.status}`);
                }
                return response.json();
            })
            .then(data => resolve(data.results))
            .catch(error => reject(error));
    });
}
                    
                        
obtenerPokemones()
    .then(pokemones => console.log("Pokémon obtenidos:", pokemones))
    .catch(error => console.error("Error en la petición:", error));
                        
                    

Encadenamiento de Promesas

Podemos encadenar múltiples `.then()` para ejecutar operaciones en secuencia.

🔹 Cada `.then()` espera el resultado del anterior antes de ejecutarse.

Async/Await

Async/Await es una forma moderna de manejar Promesas en JavaScript.

✅ Hace que el código sea más legible y estructurado.

✅ Permite manejar errores fácilmente con `try...catch`.

Cómo funciona async

Una función declarada con async siempre devuelve una promesa.


async function obtenerMensaje() {
    return "Hola, mundo!";
}

obtenerMensaje().then(console.log); // "Hola, mundo!"

Cómo funciona await

await pausa la ejecución de la función hasta que la Promesa se resuelva.


async function obtenerDatos() {
    console.log("Iniciando petición...");

    let respuesta = await fetch('https://pokeapi.co/api/v2/pokemon/');
    let datos = await respuesta.json();
    
    console.log("Datos obtenidos:", datos.results);
}

obtenerDatos();

✅ Se evita el encadenamiento de .then(), haciendo el código más claro.

Con try...catch, podemos capturar errores en operaciones await.


async function cargarDatos() {
    try {
        let respuesta = await fetch('https://pokeapi.co/api/v2/pokemon/');
        if (!respuesta.ok) throw new Error("Error en la API");
        let datos = await respuesta.json();
        
        console.log("Datos:", datos.results);
    } catch (error) {
        console.error("Error capturado:", error);
    }
}

cargarDatos();

✅ Manejo estructurado de errores sin necesidad de .catch() externo.

Ejemplo de async/await con múltiples llamadas

Podemos esperar múltiples promesas en simultaneo usando await y Promise.all().


async function obtenerDatosDePokemon() {
    try {
        // Hacemos ambas peticiones en paralelo con Promise.all
        const [listaPokemonesResponse, gengarResponse] = await Promise.all([
            fetch('https://pokeapi.co/api/v2/pokemon/'),
            fetch('https://pokeapi.co/api/v2/pokemon/gengar')
        ]);

        // Verificamos si ambas respuestas son exitosas
        if (!listaPokemonesResponse.ok) {
            throw new Error(`Error HTTP en la lista de Pokémon:`);
        }
        if (!gengarResponse.ok) {
            throw new Error(`Error HTTP en el Pokémon Gengar`);
        }

        // Convertimos las respuestas a JSON
        const listaPokemones = await listaPokemonesResponse.json();
        const gengar = await gengarResponse.json();

        return { listaPokemones: listaPokemones.results, gengar };
    } catch (error) {
        console.error("Error en la petición:", error);
    }
}
                        
obtenerDatosDePokemon().then(datos => {
    console.log("Lista de Pokémon:", datos.listaPokemones);
    console.log("Datos de Gengar:", datos.gengar);
});
                        
                    

Deconstrucción de Objetos

La deconstrucción permite extraer valores de objetos y arrays fácilmente.

✅ Hace el código más limpio y conciso.

Ejemplo


const usuario = { nombre: "Juan", edad: 25, pais: "España" };
const { nombre, edad } = usuario;

console.log(nombre, edad); // "Juan", 25

Uso en parámetros de funciones

Podemos extraer valores directamente en los parámetros de una función.


function mostrarUsuario({ nombre, pais }) {
    console.log(`Nombre: ${nombre}, País: ${pais}`);
}

const persona = { nombre: "Ana", edad: 30, pais: "México" };
mostrarUsuario(persona);

Valores por defecto

Podemos asignar valores por defecto en caso de que una propiedad no exista.


const producto = { nombre: "Laptop", precio: 1000 };
const { nombre, stock = 0 } = producto;

console.log(stock); // 0 (valor por defecto)

Renombrando variables

Podemos renombrar las variables extraídas con `:`.


const usuario = { nombre: "Pedro", edad: 22 };
const { nombre: nombreUsuario, edad: edadUsuario } = usuario;

console.log(nombreUsuario, edadUsuario); // "Pedro", 22

Desestructuración en arreglos

También funciona con arreglos, asignando variables por posición.


const colores = ["Rojo", "Verde", "Azul"];
const [primerColor, segundoColor] = colores;

console.log(primerColor, segundoColor); // "Rojo", "Verde"

Omitiendo valores en arreglos

Podemos omitir valores utilizando `,`.


const numeros = [1, 2, 3, 4, 5];
const [primero, , tercero] = numeros;

console.log(primero, tercero); // 1, 3

Uso en combinación con `fetch`

Podemos extraer datos directamente de respuestas JSON.


async function obtenerPokemon() {
    const response = await fetch('https://pokeapi.co/api/v2/pokemon/');
    const data = await response.json();
    const {name, url} = data.results[0];

    console.log(`Nombre: ${name}, URL: ${url}`);
}

obtenerPokemon();

✅ Permite acceder a los datos de una API de manera rápida y clara.

Resumen

✅ Promesas permiten manejar la asincronía sin bloquear el código.

✅ Async/Await simplifica el uso de Promesas.

✅ Fetch facilita la comunicación con APIs.

✅ Desestructuración mejora la manipulación de objetos en JavaScript.