← Node.js: JavaScript fuera del navegador

Sesión 9 · Semana 3

Errores, validación y trazas

Hoy · Hoja de ruta

  1. 1. Aprende: Cómo se distingue un fallo esperable de uno inesperado, y qué se registra de cada uno.
  2. 2. Haz: Da a tu proyecto un tratamiento de errores coherente.
  3. 3. Comprueba: Ningún fallo deja el programa a medias en silencio.

Antes de empezar · 5 minutos, sin apuntes

  1. ¿Es lo mismo «este producto no existe» que «el disco está lleno»?
  2. ¿Cuál de los dos es culpa de tu programa?
  3. ¿Qué debería quedar registrado de cada uno?

Dos familias de fallo

Familia Ejemplo Qué se hace
Esperable El producto no existe; el precio es inválido Se trata: mensaje claro y salida controlada
Inesperado Sin permisos, sin disco, un error de programación Se registra con su traza y se sale con error

Un error esperable no es una excepción

La solicitud de un producto inexistente no constituye un fallo del sistema, sino un resultado previsto. Devuélvelo como dato —null, o un resultado que lo describa— y deja las excepciones para lo que de verdad no debería pasar.

Esa distinción es la que en la UD6 se convierte en la diferencia entre responder 404 y responder 500.

Errores propios

export class ErrorDeValidacion extends Error {
  constructor(errores) {
    super("Los datos no son válidos");
    this.name = "ErrorDeValidacion";
    this.errores = errores;
  }
}

Un tipo propio permite distinguir en el catch qué clase de fallo llegó, sin comparar mensajes de texto:

catch (error) {
  if (error instanceof ErrorDeValidacion) {
    error.errores.forEach((mensaje) => console.error(` - ${mensaje}`));
    process.exit(1);
  }
  throw error;
}

Lo que nunca debe pasar desapercibido

process.on("uncaughtException", (error) => {
  console.error("Error no capturado:", error);
  process.exit(1);
});

process.on("unhandledRejection", (motivo) => {
  console.error("Promesa rechazada sin tratar:", motivo);
  process.exit(1);
});

Una promesa rechazada que nadie captura es el fallo silencioso más común de Node: el programa sigue corriendo como si nada, con una operación que no ocurrió. Estos dos manejadores son la red de seguridad; no son el sitio donde tratar los errores.

Registrar con criterio

console.error(`[${new Date().toISOString()}] crear producto falló: ${error.message}`);
Nivel Para qué
error Algo ha fallado y alguien debe mirarlo
warn Algo raro que no ha impedido continuar
info Hitos: arranque, apagado, configuración cargada
debug Detalle, solo mientras se investiga

Una regla no admite excepción: en los registros no se escriben contraseñas, tokens ni datos personales. Un fichero de log acaba copiado, enviado y guardado en sitios que nadie previó.

Tarea 9 · Errores coherentes

  1. Define ErrorDeValidacion y ErrorNoEncontrado.
  2. Haz que el almacén lance el segundo y devuelva datos en los casos normales.
  3. Trata en el CLI cada familia con su mensaje y su código de salida.
  4. Añade la red de seguridad de los dos manejadores de proceso.
  5. Registra cada operación con marca de tiempo.
  6. Provoca cuatro fallos distintos y comprueba el comportamiento de cada uno.
Objetivo mínimoDos tipos de error propios, tratados con su código de salida.
Si lo tienesEscribe los registros en un fichero además de en la terminal.
RetoProvoca una promesa rechazada sin tratar y comprueba qué pasa con y sin el manejador.

Cierre de la semana 3

  • Tus datos viven en disco y se leen y escriben sin corromperse.
  • Distingues fallos esperables de inesperados.
  • Cada error tiene su mensaje y su código de salida.
  • Nada personal acaba en los registros.
Ver respuestas

1 · No: uno es un resultado posible del negocio y el otro un fallo del sistema.

2 · Con instanceof sobre tipos de error propios, no comparando mensajes.

3 · Que el programa siga corriendo como si la operación hubiera funcionado.

Microprueba semanal 3 · 5–10 minutos

Individual, sin IA y sin apuntes.

  1. Escribe la lectura de un fichero que puede no existir, devolviendo una lista vacía en ese caso.
  2. ¿Por qué se escribe en un fichero temporal y después se renombra?
  3. Compón la ruta de datos/productos.json sin depender de la carpeta desde la que se ejecute el programa.
---