|
|
|
# Módulo 4 — Uso de Servicios y API REST
|
|
|
|
|
|
|
|
**Aplicación práctica: Conexión del sistema de gestión sanitaria con una API REST propia (consulta y actualización de recursos y personal).**
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 1. Introducción a la asincronía
|
|
|
|
|
|
|
|
JavaScript es un lenguaje **asíncrono y no bloqueante**, lo que significa que **puede ejecutar tareas sin detener el flujo principal** (por ejemplo, esperar la respuesta de un servidor mientras sigue procesando otras acciones).
|
|
|
|
|
|
|
|
Esto es posible gracias al **Event Loop** y a las **promesas (Promises)**, que permiten manejar operaciones que tardan tiempo, como peticiones a una API o lectura de archivos.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
console.log("Iniciando petición...");
|
|
|
|
setTimeout(() => {
|
|
|
|
console.log("Datos recibidos del servidor");
|
|
|
|
}, 2000);
|
|
|
|
console.log("Petición enviada");
|
|
|
|
```
|
|
|
|
|
|
|
|
> El flujo **no se detiene** esperando la respuesta del servidor.
|
|
|
|
> Se ejecuta el `setTimeout` de forma asíncrona.
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 2. Qué es una API REST
|
|
|
|
|
|
|
|
Una **API REST** (Representational State Transfer) permite **comunicarse entre aplicaciones a través de HTTP**.
|
|
|
|
Tu app de gestión sanitaria puede usar una API REST para **consultar pacientes, recursos o personal** almacenados en un servidor remoto.
|
|
|
|
|
|
|
|
Las API REST suelen **intercambiar datos en formato JSON**.
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 3. Métodos HTTP más comunes
|
|
|
|
|
|
|
|
| Método | Acción | Ejemplo en la app |
|
|
|
|
| ---------- | ------------------------------- | --------------------------------------- |
|
|
|
|
| **GET** | Obtener información | Consultar la lista de recursos |
|
|
|
|
| **POST** | Crear nuevo elemento | Añadir un nuevo paciente |
|
|
|
|
| **PUT** | Actualizar un registro completo | Editar los datos de un recurso |
|
|
|
|
| **PATCH** | Actualizar parcialmente | Cambiar solo la cantidad de mascarillas |
|
|
|
|
| **DELETE** | Eliminar un registro | Eliminar un paciente dado de alta |
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 4. Qué es JSON
|
|
|
|
|
|
|
|
**JSON (JavaScript Object Notation)** es el formato estándar de intercambio de datos entre cliente y servidor.
|
|
|
|
|
|
|
|
Se basa en **pares clave–valor**, muy similar a los objetos literales de JavaScript.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
// Objeto literal
|
|
|
|
const recurso = {
|
|
|
|
tipo: "Mascarillas",
|
|
|
|
cantidad: 300,
|
|
|
|
disponible: true
|
|
|
|
};
|
|
|
|
|
|
|
|
// Conversión a JSON
|
|
|
|
const json = JSON.stringify(recurso);
|
|
|
|
console.log(json); // '{"tipo":"Mascarillas","cantidad":300,"disponible":true}'
|
|
|
|
|
|
|
|
// Convertir JSON a objeto
|
|
|
|
const obj = JSON.parse(json);
|
|
|
|
console.log(obj.tipo); // "Mascarillas"
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 5. Peticiones HTTP con `fetch()`
|
|
|
|
|
|
|
|
La función **`fetch()`** permite realizar peticiones HTTP de forma asíncrona.
|
|
|
|
Devuelve una **Promise**, lo que significa que podemos usar `.then()` o `async/await`.
|
|
|
|
|
|
|
|
### Ejemplo: obtener recursos del servidor
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
fetch("https://api.hospitalcentral.com/recursos")
|
|
|
|
.then(res => res.json())
|
|
|
|
.then(data => {
|
|
|
|
console.log("Recursos disponibles:", data);
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
console.error("Error al obtener los datos:", error);
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 6. Uso de `async` y `await`
|
|
|
|
|
|
|
|
La sintaxis `async/await` simplifica el manejo de promesas, haciéndolo más legible y cercano al código secuencial.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
async function cargarRecursos() {
|
|
|
|
try {
|
|
|
|
const respuesta = await fetch("https://api.hospitalcentral.com/recursos");
|
|
|
|
const datos = await respuesta.json();
|
|
|
|
console.table(datos);
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Error al cargar recursos:", error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cargarRecursos();
|
|
|
|
```
|
|
|
|
|
|
|
|
> `await` detiene la ejecución dentro de la función **asíncrona** hasta que se resuelve la promesa.
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 7. Envío de datos (POST)
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
async function agregarRecurso() {
|
|
|
|
const nuevo = {
|
|
|
|
tipo: "Guantes",
|
|
|
|
cantidad: 150
|
|
|
|
};
|
|
|
|
|
|
|
|
const respuesta = await fetch("https://api.hospitalcentral.com/recursos", {
|
|
|
|
method: "POST",
|
|
|
|
headers: { "Content-Type": "application/json" },
|
|
|
|
body: JSON.stringify(nuevo)
|
|
|
|
});
|
|
|
|
|
|
|
|
const resultado = await respuesta.json();
|
|
|
|
console.log("Recurso agregado:", resultado);
|
|
|
|
}
|
|
|
|
|
|
|
|
agregarRecurso();
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 8. Actualización y eliminación
|
|
|
|
|
|
|
|
### PATCH (actualizar registro completo)
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
async function actualizarRecurso(id) {
|
|
|
|
const recursoActualizado = {
|
|
|
|
tipo: "Guantes estériles",
|
|
|
|
cantidad: 200
|
|
|
|
};
|
|
|
|
|
|
|
|
await fetch(`https://api.hospitalcentral.com/recursos/${id}`, {
|
|
|
|
method: "PATCH",
|
|
|
|
headers: { "Content-Type": "application/json" },
|
|
|
|
body: JSON.stringify(recursoActualizado)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### DELETE (eliminar registro)
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
async function eliminarRecurso(id) {
|
|
|
|
await fetch(`https://api.hospitalcentral.com/recursos/${id}`, {
|
|
|
|
method: "DELETE"
|
|
|
|
});
|
|
|
|
console.log("Recurso eliminado correctamente");
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 9. CORS (Cross-Origin Resource Sharing)
|
|
|
|
|
|
|
|
**CORS** es un mecanismo de seguridad que controla qué dominios pueden acceder a los recursos de una API.
|
|
|
|
Si tu frontend (`http://localhost:3000`) intenta acceder a una API en otro dominio (`https://api.hospitalcentral.com`), el servidor debe **permitir explícitamente** esa conexión.
|
|
|
|
|
|
|
|
Ejemplo de encabezado que el servidor debe devolver:
|
|
|
|
|
|
|
|
```
|
|
|
|
Access-Control-Allow-Origin: http://localhost:3000
|
|
|
|
```
|
|
|
|
|
|
|
|
> Si CORS no está configurado, el navegador **bloqueará la petición por seguridad**.
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 10. Ejemplo práctico: mostrar recursos en la interfaz
|
|
|
|
|
|
|
|
```html
|
|
|
|
<h2>Recursos disponibles</h2>
|
|
|
|
<ul id="lista"></ul>
|
|
|
|
<button id="btnCargar">Cargar recursos</button>
|
|
|
|
```
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
const btn = document.getElementById("btnCargar");
|
|
|
|
const lista = document.getElementById("lista");
|
|
|
|
|
|
|
|
btn.addEventListener("click", async () => {
|
|
|
|
try {
|
|
|
|
const res = await fetch("https://api.hospitalcentral.com/recursos");
|
|
|
|
const recursos = await res.json();
|
|
|
|
lista.innerHTML = ""; // limpiar lista previa
|
|
|
|
|
|
|
|
recursos.forEach(r => {
|
|
|
|
const li = document.createElement("li");
|
|
|
|
li.textContent = `${r.tipo}: ${r.cantidad}`;
|
|
|
|
lista.appendChild(li);
|
|
|
|
});
|
|
|
|
} catch (error) {
|
|
|
|
alert("Error al cargar recursos");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
> Este ejemplo conecta la **interfaz del DOM** con la **API REST**, mostrando datos dinámicamente desde el servidor.
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
## 11. Buenas prácticas
|
|
|
|
|
|
|
|
- Usa `async/await` para código más legible.
|
|
|
|
- Maneja siempre los **errores** con `try...catch` al hacer peticiones a servicios externos.
|
|
|
|
- No compartas claves o URLs sensibles en el frontend.
|
|
|
|
- Define funciones reutilizables para las peticiones.
|
|
|
|
- Asegúrate de que tu servidor tenga configurado **CORS** correctamente.
|
|
|
|
|