Skip to main content

Manejo de Respuestas HTTP

Cuando haces una petición con fetch(), recibes un objeto Response. Este objeto contiene información sobre la respuesta del servidor y métodos para procesar los datos.

El Objeto Response

const response = await fetch('https://api.ejemplo.com/datos');

console.log(response.status);     // 200, 404, 500, etc.
console.log(response.statusText); // "OK", "Not Found", etc.
console.log(response.ok);         // true si status es 200-299
console.log(response.headers);    // Headers del servidor
console.log(response.url);        // URL final (después de redirects)

Propiedades Importantes

Boolean que indica si la respuesta fue exitosa (status 200-299).
if (!response.ok) {
  throw new Error(`HTTP error ${response.status}`);
}
Es la forma más simple de verificar si hubo un error.
Código de estado HTTP numérico.
if (response.status === 404) {
  console.log('Recurso no encontrado');
} else if (response.status === 500) {
  console.log('Error del servidor');
}
Mensaje de texto asociado al código de estado.
console.log(response.statusText); // "OK", "Not Found", etc.
Objeto Headers con las cabeceras de respuesta.
const contentType = response.headers.get('Content-Type');
console.log(contentType); // "application/json"

Procesar el Cuerpo de la Respuesta

El cuerpo de la respuesta debe ser procesado con uno de estos métodos:

response.json()

Parsea el cuerpo como JSON. Retorna una Promise.
async function cargarUsuarios() {
  try {
    var response = await fetch(url);
    if (!response.ok) {
      throw new Error("HTTP status " + response.status);
    }
    var data = await response.json();
    console.log("Users (async/await):", data);
    printUsers(data);
  } catch (error) {
    console.log(error);
    usersOutput.textContent = error;
  }
}
Si el cuerpo no es JSON válido, response.json() lanzará un error. Asegúrate de que el Content-Type sea application/json.

response.text()

Obtiene el cuerpo como texto plano:
const response = await fetch('/archivo.txt');
const texto = await response.text();
console.log(texto);

response.blob()

Para archivos binarios (imágenes, PDFs, etc.):
const response = await fetch('/imagen.jpg');
const blob = await response.blob();

// Crear una URL para mostrar la imagen
const imageUrl = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = imageUrl;
document.body.appendChild(img);

response.arrayBuffer()

Para datos binarios en bruto:
const response = await fetch('/datos.bin');
const buffer = await response.arrayBuffer();

response.formData()

Para datos de formulario:
const response = await fetch('/formulario');
const formData = await response.formData();
Cada uno de estos métodos puede llamarse solo UNA vez. El cuerpo de la respuesta es un stream que se consume.

Verificar Códigos de Estado

Manejo Básico con response.ok

const response = await fetch(url);

if (!response.ok) {
  throw new Error(`HTTP status ${response.status}`);
}

const data = await response.json();

Manejo Específico por Código

const response = await fetch(url);

switch (response.status) {
  case 200:
    const data = await response.json();
    console.log('Datos recibidos:', data);
    break;
    
  case 404:
    console.error('Recurso no encontrado');
    break;
    
  case 401:
    console.error('No autorizado - inicia sesión');
    break;
    
  case 500:
    console.error('Error del servidor');
    break;
    
  default:
    console.error(`Error HTTP ${response.status}`);
}

Ejemplo Completo: Verificación de Respuesta

function cargarUsuariosThen() {
  usersOutput.textContent = "Cargando...";
  fetch(url)
    .then(function (response) {
      // Verificar si la respuesta es exitosa
      if (!response.ok) {
        throw new Error("HTTP status " + response.status);
      }
      // Parsear JSON
      return response.json();
    })
    .then(function (data) {
      console.log("Users (.then):", data);
      printUsers(data);
    })
    .catch(function (error) {
      console.log(error);
      usersOutput.textContent = error;
    });
}

Manejar Errores de Red

Fetch rechaza la Promise solo en errores de red (sin conexión, DNS falla, etc.), NO en errores HTTP:
try {
  const response = await fetch(url);
  
  // Esto NO se ejecutará en un 404 o 500
  // Solo se ejecuta en errores de red
  
  if (!response.ok) {
    throw new Error(`HTTP error ${response.status}`);
  }
  
  const data = await response.json();
  
} catch (error) {
  // Maneja errores de red Y errores HTTP que lanzaste
  console.error('Error:', error);
}
Por eso es crucial verificar response.ok - los errores HTTP no lanzan excepciones automáticamente.

Leer Headers de Respuesta

const response = await fetch(url);

// Obtener un header específico
const contentType = response.headers.get('Content-Type');
console.log('Content-Type:', contentType);

// Verificar si existe un header
if (response.headers.has('X-Custom-Header')) {
  console.log('Header personalizado presente');
}

// Iterar sobre todos los headers
for (const [key, value] of response.headers) {
  console.log(`${key}: ${value}`);
}

Timeout y Abortar Peticiones

Usando AbortController

const controller = new AbortController();
const signal = controller.signal;

// Abortar después de 5 segundos
setTimeout(() => controller.abort(), 5000);

try {
  const response = await fetch(url, { signal });
  const data = await response.json();
  console.log(data);
} catch (error) {
  if (error.name === 'AbortError') {
    console.log('Petición abortada por timeout');
  } else {
    console.error('Error:', error);
  }
}

Función Helper con Timeout

function fetchConTimeout(url, timeout = 5000) {
  return new Promise((resolve, reject) => {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => {
      controller.abort();
      reject(new Error('Timeout'));
    }, timeout);
    
    fetch(url, { signal: controller.signal })
      .then(response => {
        clearTimeout(timeoutId);
        resolve(response);
      })
      .catch(error => {
        clearTimeout(timeoutId);
        reject(error);
      });
  });
}

// Uso
try {
  const response = await fetchConTimeout('/api/data', 3000);
  const data = await response.json();
} catch (error) {
  console.error('Error o timeout:', error);
}

Respuestas con Diferentes Content-Types

const response = await fetch(url);
const data = await response.json();
console.log(data);

Buenas Prácticas

1

Siempre verifica response.ok

if (!response.ok) {
  throw new Error(`HTTP error ${response.status}`);
}
2

Maneja errores apropiadamente

try {
  const response = await fetch(url);
  if (!response.ok) throw new Error(response.status);
  const data = await response.json();
} catch (error) {
  console.error('Error:', error);
  // Mostrar mensaje al usuario
}
3

Verifica el Content-Type

const contentType = response.headers.get('Content-Type');
if (contentType && contentType.includes('application/json')) {
  const data = await response.json();
} else {
  const text = await response.text();
}
4

Proporciona feedback al usuario

mostrarCargando();
try {
  const data = await fetch(url).then(r => r.json());
  mostrarDatos(data);
} catch (error) {
  mostrarError(error);
} finally {
  ocultarCargando();
}

Próximos Pasos

localStorage

Guarda datos en el navegador permanentemente

Ejemplos de Fetch

Ve ejemplos completos de uso de Fetch

Build docs developers (and LLMs) love