Hoy · Hoja de ruta
- 1. Aprende: Cómo se traduce cada error interno a una respuesta HTTP, en un solo sitio.
- 2. Haz: Cierra el manejador central y comprueba todos los casos.
- 3. Comprueba: Ninguna ruta decide ya un código de estado por su cuenta.
Antes de empezar · 5 minutos, sin apuntes
- ¿Cuántos sitios de tu código deciden hoy un código de estado?
- Si añades un tipo de error nuevo, ¿cuántos ficheros tocas?
- ¿Qué debe ver el cliente cuando el fallo es tuyo?
La traducción, en un solo sitio
const ESTADOS = {
ErrorDeValidacion: 400,
ErrorNoAutenticado: 401,
ErrorSinPermiso: 403,
ErrorNoEncontrado: 404,
ErrorDeConflicto: 409
};
export function manejadorDeErrores(error, peticion, respuesta, next) {
const estado = ESTADOS[error.name] ?? 500;
if (estado >= 500) {
console.error(`[${peticion.id}] ${peticion.method} ${peticion.originalUrl}`, error);
}
respuesta.status(estado).json({
error: estado >= 500 ? "Error interno del servidor" : error.message,
codigo: error.codigo ?? error.name ?? "ERROR",
detalles: error.detalles ?? [],
peticion: peticion.id
});
}
Añadir un tipo de error nuevo se reduce a añadir una línea a la tabla, sin que ninguna ruta necesite conocer qué código corresponde a su fallo.
El identificador de petición
export function identificar(peticion, respuesta, next) {
peticion.id = crypto.randomUUID();
respuesta.setHeader("X-Request-Id", peticion.id);
next();
}
Un identificador convierte «me da error» en un caso investigable
El cliente ve un mensaje genérico y un identificador. Ese mismo identificador está en tus registros junto a la traza completa. Quien reporta el problema te da el número, y tú encuentras exactamente su petición entre miles.
Es lo que permite no filtrar detalles internos sin quedarte ciego para diagnosticar.
El cliente, del otro lado
async function pedir(url, opciones) {
const respuesta = await fetch(url, opciones);
if (respuesta.ok) return respuesta.status === 204 ? null : respuesta.json();
const cuerpo = await respuesta.json().catch(() => ({}));
throw new ErrorDeApi(respuesta.status, cuerpo.error ?? "Error inesperado", cuerpo.detalles ?? []);
}
Aquí se cobra el contrato: una sola función en el cliente sirve para toda la API, hoy y cuando añadas rutas. Si cada error tuviera una forma distinta, esta función no podría existir.
Tarea 9 · Errores de punta a punta
- Define los cinco tipos de error de tu aplicación.
- Escribe la tabla de traducción y el manejador central.
- Añade el identificador de petición y sácalo en registro y respuesta.
- Elimina todos los códigos de estado repartidos por las rutas.
- Escribe la función
pediren el cliente y úsala en toda la interfaz. - Provoca los cinco errores desde el cliente y comprueba qué se ve y qué se registra.
Cierre de la semana 3
- Las tres capas están separadas de verdad.
- Puedes cambiar de almacén sin tocar rutas ni servicio.
- Los errores se traducen a HTTP en un solo sitio.
- El cliente trata todos los errores con una sola función.
Ver respuestas
1 · En el manejador central de errores, con una tabla de traducción.
2 · Para poder relacionar lo que ve el cliente con la traza de tus registros.
3 · Un mensaje genérico: el detalle se queda en el servidor.
Microprueba semanal 3 · 5–10 minutos
Individual, sin IA y sin apuntes.
- Di a qué capa pertenece cada cosa: escribir un 404, «no se puede borrar con stock», y leer el fichero de datos.
- ¿Cómo compruebas que tus capas están separadas de verdad?
- ¿Por qué el cliente nunca debe ver la traza de un error?