07 - Consumo de APIs REST
Desde el navegador o Node, la función fetch envía peticiones HTTP a una API REST y devuelve una promesa con la respuesta. Es el mecanismo con el que el front de TypeScript consume las APIs creadas en Programación.
1. fetch y async/await
async function getBook(id: number): Promise<BookResponse> {
const response = await fetch(`/api/books/${id}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
}
awaitpausa hasta que llega la respuesta sin bloquear el hilo.response.okestruecon códigos 2xx.response.json()lee y parsea el cuerpo como JSON.
Una función async devuelve una Promise; el error se captura con try/catch:
try {
const book = await getBook(42);
render(book);
} catch (error) {
showErrorMessage("No se pudo cargar el libro");
}
2. GET y POST
// GET: petición por defecto
const books = await fetch("/api/books?genre=novel").then(r => r.json());
// POST: envía un cuerpo JSON
async function createBook(book: CreateBookRequest): Promise<void> {
const response = await fetch("/api/books", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(book),
});
if (response.status !== 201) {
throw new Error(`HTTP ${response.status}`);
}
}
| Método | Uso |
|---|---|
GET | Consultar; sin cuerpo |
POST | Crear; cuerpo JSON |
PUT | Reemplazar un recurso |
DELETE | Eliminar |
3. Cabeceras
headers: {
"Content-Type": "application/json", // formato del cuerpo enviado
"Accept": "application/json", // formato esperado en la respuesta
"Authorization": `Bearer ${token}` // autenticación
}
4. Autenticación con tokens
La API de login de Programación entrega un token de acceso; el cliente lo guarda y lo envía en cada petición protegida:
async function login(email: string, password: string): Promise<TokenPair> {
const response = await fetch("/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
if (!response.ok) {
throw new Error("Invalid credentials");
}
return response.json(); // { accessToken, refreshToken }
}
async function getProfile(token: string): Promise<UserResponse> {
const response = await fetch("/auth/me", {
headers: { "Authorization": `Bearer ${token}` },
});
if (response.status === 401) {
// token caducado o inválido: renovar o pedir login
}
return response.json();
}
| Respuesta | Interpretación |
|---|---|
200/201 | Operación correcta |
400 | Petición mal formada |
401 | Token ausente, caducado o inválido |
403 | Autenticado pero sin permisos |
404 | Recurso inexistente |
5. Errores
El cuerpo de error es también JSON, con un formato acordado por la API:
{ "code": "USER_ALREADY_EXISTS", "message": "No se puede crear el usuario" }
Guarda el token en memoria o en
sessionStorage, nunca lo imprimas en logs. Si la respuesta es 401, usa el refresh token para renovar el par y repite la petición.