En esta página
Fetch API
Qué es Fetch API?
fetch() es la API nativa del navegador para hacer peticiones HTTP. Reemplaza al antiguo XMLHttpRequest con una interfaz basada en promesas, más limpia y moderna.
const respuesta = await fetch(url, opciones);Retorna una Response que contiene el estado HTTP, headers y métodos para leer el cuerpo.
Métodos HTTP
| Método | Uso | Tiene body? |
|---|---|---|
GET |
Obtener datos | No |
POST |
Crear un recurso | Si |
PUT |
Reemplazar un recurso | Si |
PATCH |
Actualizar parcialmente | Si |
DELETE |
Eliminar un recurso | Generalmente no |
El objeto Response
La respuesta de fetch tiene propiedades y métodos importantes:
| Propiedad/Método | Descripcion |
|---|---|
response.ok |
true si el status es 200-299 |
response.status |
Código HTTP (200, 404, 500, etc.) |
response.statusText |
Texto del estado ("OK", "Not Found") |
response.headers |
Headers de la respuesta |
response.json() |
Lee el cuerpo como JSON (promesa) |
response.text() |
Lee el cuerpo como texto (promesa) |
response.blob() |
Lee el cuerpo como Blob (promesa) |
Nota importante sobre .ok
fetch no rechaza la promesa ante errores HTTP (404, 500, etc.). Solo rechaza ante errores de red (sin conexión, DNS fallido). Siempre verifica response.ok:
const res = await fetch('/api/data');
if (!res.ok) {
throw new Error(`Error HTTP: ${res.status}`);
}
const data = await res.json();Headers y body
Para enviar datos, configura los headers y el body:
const res = await fetch('/api/items', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer token123',
},
body: JSON.stringify({ nombre: 'Item', precio: 42 }),
});El body se serializa con JSON.stringify(). Los headers indican al servidor el formato de los datos.
AbortController
Permite cancelar peticiones en curso. Es esencial para:
- Buscadores — Cancelar la petición anterior al escribir
- Navegación — Cancelar peticiones pendientes al cambiar de página
- Timeouts — Cancelar peticiones que tardan demasiado
const controller = new AbortController();
fetch(url, { signal: controller.signal });
controller.abort(); // cancela la peticiónURLSearchParams
Para construir query strings de forma segura (con encoding automático):
const params = new URLSearchParams({
buscar: 'hola mundo',
página: '1',
});
console.log(params.toString()); // "buscar=hola+mundo&página=1"Wrapper reutilizable
En proyectos reales, crea una función wrapper que centralice la lógica comun: base URL, headers por defecto, manejo de errores y serialización.
Práctica
- Haz un GET con validacion: Escribe una funcion async
obtenerDatos(url)que haga unfetchGET, verifiqueresponse.ok, y retorne los datos parseados como JSON. Maneja los errores HTTP lanzando unErrorcon el codigo de estado. - Envia datos con POST: Crea una funcion
enviarFormulario(url, datos)que haga unfetchPOST conContent-Type: application/jsony el body serializado conJSON.stringify. Verifica la respuesta y retorna el resultado. - Construye una URL con parametros: Usa
URLSearchParamspara construir una URL con los parametrosbuscar,paginaylimite. Imprime la URL completa en consola.
En la siguiente leccion aprenderemos sobre módulos ES para organizar nuestro código.
// GET básico
async function obtenerUsuarios() {
const respuesta = await fetch('https://api.ejemplo.com/users');
// Verificar estado HTTP
if (!respuesta.ok) {
throw new Error(`HTTP ${respuesta.status}: ${respuesta.statusText}`);
}
const usuarios = await respuesta.json();
return usuarios;
}
// POST - enviar datos
async function crearUsuario(datos) {
const respuesta = await fetch('https://api.ejemplo.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(datos),
});
if (!respuesta.ok) {
const error = await respuesta.json();
throw new Error(error.message);
}
return respuesta.json();
}
// PUT - actualizar
async function actualizarUsuario(id, datos) {
return fetch(`https://api.ejemplo.com/users/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(datos),
});
}
// DELETE
async function eliminarUsuario(id) {
const res = await fetch(`https://api.ejemplo.com/users/${id}`, {
method: 'DELETE',
});
if (!res.ok) throw new Error('No se pudo eliminar');
}
// Uso
const nuevo = await crearUsuario({
nombre: 'Maria',
email: '[email protected]',
});
console.log('Creado:', nuevo);
// AbortController - cancelar peticiones
const controller = new AbortController();
async function buscar(término) {
try {
const res = await fetch(`/api/search?q=${término}`, {
signal: controller.signal,
});
return res.json();
} catch (error) {
if (error.name === 'AbortError') {
console.log('Peticion cancelada');
} else {
throw error;
}
}
}
// Cancelar la petición
controller.abort();
// Query parameters con URLSearchParams
function construirURL(base, params) {
const url = new URL(base);
const searchParams = new URLSearchParams(params);
url.search = searchParams.toString();
return url.toString();
}
const url = construirURL('https://api.ejemplo.com/products', {
categoria: 'tech',
orden: 'precio',
página: '1',
limite: '20',
});
// https://api.ejemplo.com/products?categoria=tech&orden=precio&página=1&limite=20
// Wrapper reutilizable
async function api(endpoint, opciones = {}) {
const config = {
headers: { 'Content-Type': 'application/json' },
...opciones,
body: opciones.body ? JSON.stringify(opciones.body) : undefined,
};
const respuesta = await fetch(`/api${endpoint}`, config);
if (!respuesta.ok) {
const error = await respuesta.json().catch(() => ({}));
throw new Error(error.message || `HTTP ${respuesta.status}`);
}
return respuesta.json();
}
// Uso del wrapper
const users = await api('/users');
const post = await api('/posts', {
method: 'POST',
body: { título: 'Nuevo post', contenido: '...' },
});
Inicia sesión para guardar tu progreso