Cuando desarrollamos para la web, es una tarea común y crítica, el consumo de servicios de datos, que serán parte fundamental de nuestra aplicación. Siendo que JavaScript es el lenguaje que usamos para dar interactividad, revisemos como consumir APIs desde nuestras aplicaciones web, para obtener y manipular datos de forma dinámica. En las siguientes líneas vamos a verificar cómo funcionan las solicitudes HTTP, el uso de fetch y el papel de async/await en el consumo de APIs. Usaremos la API de REST Countries como ejemplo, permitiéndonos acceder y mostrar datos detallados sobre países en una aplicación interactiva.

Introducción a las APIs y REST

¿Qué es una API?

API, o Interfaz de Programación de Aplicaciones (Application Programming Interface), es un conjunto de reglas y protocolos que permite que dos aplicaciones se comuniquen entre sí. Piensa en una API como un puente que conecta dos aplicaciones: una puede pedirle datos o servicios a otra sin necesidad de conocer su funcionamiento interno.

¿Qué es REST?

REST, o Transferencia de Estado Representacional (Representational State Transfer), es un estilo arquitectónico para diseñar APIs. Las APIs REST suelen usar URLs para identificar recursos (como países, en nuestro caso) y métodos HTTP (GET, POST, PUT, DELETE) para definir las acciones a realizar sobre esos recursos.

Métodos HTTP en el Consumo de APIs

Las APIs REST se basan en el protocolo HTTP, el cual es el mismo protocolo que usamos al navegar en la web. Cada acción que llevamos a cabo con la API (consultar datos, crear un nuevo registro, actualizar o eliminar un registro) se representa a través de un método HTTP. Estos métodos son parte integral de la arquitectura REST, ya que permiten manipular recursos de forma estandarizada.

Cada método HTTP tiene un propósito específico y su propio rol en la interacción con la API:

GET: Este es el método más común y se usa para recuperar datos de un recurso específico. Es como una consulta de solo lectura; no cambia ni afecta el estado de los datos en el servidor.

  • Ejemplo: Al consultar la API para obtener una lista de países, usamos una solicitud GET.

POST: Este método se utiliza para enviar datos al servidor y crear un nuevo recurso en él. A diferencia de GET, POST modifica el estado del servidor al agregar datos.

  • Ejemplo: En una API de usuarios, un POST a la URL https://api.ejemplo.com/usuarios podría crear un nuevo usuario en la base de datos.

PUT: Se usa para actualizar un recurso existente en el servidor. En general, se espera que una solicitud PUT contenga todos los datos del recurso a actualizar, y reemplaza el recurso en el servidor con los datos enviados.

  • Ejemplo: Actualizar los detalles de un país en la base de datos mediante una solicitud PUT a https://api.ejemplo.com/paises/{id}.

DELETE: Este método se utiliza para eliminar un recurso específico en el servidor. Como su nombre lo indica, DELETE quita o borra datos de la base de datos o sistema remoto.

  • Ejemplo: Una solicitud DELETE a https://api.ejemplo.com/usuarios/{id} eliminaría al usuario con el ID especificado.

Cada uno de estos métodos se representa en las aplicaciones REST de forma clara, permitiendo a los desarrolladores y al servidor entender qué acción se desea realizar sobre los datos. Estos métodos, cuando se usan con fetch en JavaScript, nos permiten manipular y gestionar datos de manera precisa y efectiva en la aplicación.

Ejemplo de Solicitudes HTTP con fetch

El método fetch en JavaScript nos permite implementar fácilmente cualquiera de estos métodos HTTP:

  • GET: Para recuperar datos, pasamos solo la URL a fetch.
  • POST, PUT y DELETE: Estos métodos requieren configuraciones adicionales en fetch, como el tipo de método, los encabezados y el cuerpo de la solicitud.

Uso de fetch en JavaScript

fetch es una función nativa en JavaScript que facilita el envío de solicitudes HTTP, devolviendo una promesa. Usar fetch con async/await mejora la legibilidad del código y simplifica la gestión de las respuestas, lo que es especialmente útil cuando trabajamos con datos de una API.

Estructura Básica de fetch

La sintaxis básica de fetch para una solicitud GET es:

fetch(url)
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));

O usando async/await:

async function getData(url) {
    try {
        const response = await fetch(url);
        const data = await response.json();
        console.log(data);
    } catch (error) {
        console.error('Error:', error);
    }
}

Solicitud GET con fetch

En una solicitud GET, simplemente se pasa la URL de la API a fetch. Nuestro ejemplo utiliza este método para obtener datos de países según su subregión.

async function getDatos(subregion) {
    try {
        const res = await fetch(`https://restcountries.com/v3.1/subregion/${subregion}`);
        const data = await res.json();
        dibujaCards(data);
    } catch (error) {
        alert('No pude conectarme a la API');
    }
}

Solicitud POST, PUT y DELETE con fetch

Para otras operaciones (POST, PUT, DELETE), podemos añadir una configuración adicional a fetch, especificando el método, encabezados y el cuerpo de la solicitud.

Ejemplo de POST

Un ejemplo típico de POST podría ser enviar datos a una API para crear un nuevo recurso, como un usuario.

async function createUser(userData) {
    try {
        const response = await fetch('https://example.com/api/users', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(userData)
        });
        const data = await response.json();
        console.log('Usuario creado:', data);
    } catch (error) {
        console.error('Error al crear usuario:', error);
    }
}

Ejemplo de PUT

PUT se usa para actualizar un recurso existente. Este ejemplo muestra cómo modificar los datos de un usuario:

async function updateUser(userId, updatedData) {
    try {
        const response = await fetch(`https://example.com/api/users/${userId}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(updatedData)
        });
        const data = await response.json();
        console.log('Usuario actualizado:', data);
    } catch (error) {
        console.error('Error al actualizar usuario:', error);
    }
}

Ejemplo de DELETE

Para eliminar un recurso, simplemente usamos el método DELETE y la URL correspondiente.

async function deleteUser(userId) {
    try {
        const response = await fetch(`https://example.com/api/users/${userId}`, {
            method: 'DELETE'
        });
        if (response.ok) {
            console.log('Usuario eliminado');
        }
    } catch (error) {
        console.error('Error al eliminar usuario:', error);
    }
}

Proyecto: Explorador de Países

Vamos a crear una pequeña aplicación, que consuma datos de la API de REST Countries y poder generar una presentación de galería, así como una presentación de detalle por país, con ello vamos a poder poner en práctica los conceptos anteriormente explicados.

Proyecto: Explorador de Países

El proyecto está compuesto por:

  1. HTML (index.html): Define la estructura de la aplicación.
  2. JavaScript (script.js): Realiza la solicitud a la API para obtener datos de países según la subregión seleccionada.
  3. HTML (detail.html): Define la estructura de la presentación de detalle del país.
  4. JavaScript de Detalle (detail.js): Muestra detalles específicos de un país.

HTML de la Página Principal

En el archivo index.html, configuramos una barra de navegación para seleccionar una subregión (América del Norte, América del Sur o América Central) y una galería donde se muestran los países.

<nav>
    <ul class="navbar">
        <li><a href="#norteamerica">América del Norte</a></li>
        <li><a href="#suramerica">América del Sur</a></li>
        <li><a href="#centroamerica">América Central</a></li>
    </ul>
</nav>
<div id="loading" class="loading hidden">Cargando...</div>
<section class="gallery"></section>
<footer>
    <p>&copy; 2024 América - Explorando Países</p>
</footer>

Función para Obtener Datos en script.js

Aquí, fetch se usa para hacer una solicitud GET a la API y obtener datos sobre países de una subregión. Se muestra un indicador de carga durante la consulta y se actualiza la galería una vez que se reciben los datos.

const loadingIndicator = document.getElementById('loading');

function showLoading() {
    loadingIndicator.classList.remove('hidden');
}

function hideLoading() {
    loadingIndicator.classList.add('hidden');
}

async function getDatos(subregion) {
    try {
        showLoading();
        const res = await fetch(`https://restcountries.com/v3.1/subregion/${subregion}`);
        const data = await res.json();
        dibujaCards(data);
    } catch (error) {
        alert('No pude conectarme a la API');
    } finally {
        hideLoading();
    }
}

Función dibujaCards(paises)

Esta función recibe los datos de la API y los muestra en una tarjeta HTML para cada país.

function dibujaCards(paises) {
    const galeria = document.querySelector('.gallery');
    let htmlPaises = '';
    paises.forEach((pais) => {
        htmlPaises += `
        <div class="card">
            <h2>${pais.name.official}</h2>
            <p><strong>Capital:</strong> ${pais.capital ? pais.capital[0] : 'No Disponible'}</p>
            <p><strong>Idioma:</strong> ${Object.values(pais.languages || { '': 'No Disponible' }).join(', ')}</p>
            <button onclick="viewMore('${pais.cca3}')">Ver más</button>
        </div>
        `;
    });
    galeria.innerHTML = htmlPaises;
}

Resumiendo lo realizado,  fetch y async/await nos brindan una forma poderosa y sencilla de consumir APIs en JavaScript. Al conocer los diferentes métodos HTTP y cómo configurarlos en fetch, ahora tienes las bases para manejar solicitudes GET, POST, PUT y DELETE, lo cual te abrirá muchas posibilidades para crear aplicaciones interactivas que consuman o modifiquen datos de forma dinámica.