Aprende a utilizar la API Fetch para realizar peticiones HTTP modernas en JavaScript. Esta guía cubre desde conceptos básicos hasta técnicas avanzadas para consumir APIs RESTful con manejo de errores, autenticación y optimización.
Diagrama de flujo de una petición HTTP con Fetch API
Contenido del Artículo
Conceptos Básicos de Fetch
Sintaxis básica para peticiones GET:
Asíncrono
Devuelve una Promesa
Moderno
Reemplaza a XMLHttpRequest
Navegadores
Soportado en todos los navegadores modernos
// Petición GET simple
fetch('https://api.ejemplo.com/data')
.then(response => {
if (!response.ok) {
throw new Error('Error en la respuesta');
}
return response.json(); // Parsear JSON
})
.then(data => {
console.log(data);
})
.catch(error => {
console.error('Error:', error);
});
Opciones Avanzadas
Configuración de métodos, cabeceras y cuerpo:
// Petición POST con JSON
fetch('https://api.ejemplo.com/usuarios', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token-abc123'
},
body: JSON.stringify({
nombre: 'Carlos',
email: 'carlos@ejemplo.com'
})
})
.then(response => response.json())
.then(data => console.log('Éxito:', data))
.catch(error => console.error('Error:', error));
// Subir archivo
const formData = new FormData();
formData.append('archivo', fileInput.files[0]);
fetch('https://api.ejemplo.com/subir', {
method: 'POST',
body: formData
});
Opción | Descripción | Valores comunes |
---|---|---|
method | Método HTTP | GET, POST, PUT, DELETE, PATCH |
headers | Cabeceras de petición | Content-Type, Authorization |
body | Cuerpo de petición | String, FormData, Blob |
mode | Modo de petición | cors, no-cors, same-origin |
cache | Gestión de caché | default, no-store, reload |
credentials | Envío de credenciales | include, same-origin, omit |
Manejo Avanzado de Errores
Estrategias para diferentes tipos de errores:
async function fetchData() {
try {
const response = await fetch('https://api.ejemplo.com/data');
if (response.status === 404) {
throw new Error('Recurso no encontrado');
}
if (response.status === 401) {
// Manejar token expirado
return refreshTokenAndRetry();
}
if (!response.ok) {
throw new Error(`Error HTTP: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error('Error en fetch:', error);
// Mostrar mensaje al usuario
showNotification(`Error: ${error.message}`);
// Relanzar para manejo superior
throw error;
}
}
Fetch no rechaza en errores HTTP 4xx/5xx - debes verificar response.ok
Optimización y Buenas Prácticas
Técnicas para mejorar rendimiento y seguridad:
AbortController
Cancelar peticiones lentas
Seguridad
Validar respuestas, sanitizar datos
Reintentos
Exponencial backoff para fallos
Caché
Estrategias para datos estáticos
// Cancelar petición con AbortController
const controller = new AbortController();
const signal = controller.signal;
setTimeout(() => controller.abort(), 5000); // Timeout después de 5s
try {
const response = await fetch('https://api.ejemplo.com/data', {
signal
});
// ...
} catch (error) {
if (error.name === 'AbortError') {
console.log('Petición cancelada');
} else {
// Manejar otros errores
}
}
// Reintento con backoff exponencial
async function fetchWithRetry(url, options = {}, retries = 3) {
try {
return await fetch(url, options);
} catch (error) {
if (retries <= 0) throw error;
const delay = 1000 * (4 - retries); // 1s, 2s, 3s
await new Promise(res => setTimeout(res, delay));
return fetchWithRetry(url, options, retries - 1);
}
}