Saltar al contenido
excepciones.js · devschool

Errores y excepciones en JavaScript

Lección 19 de 38 · 4 min de lectura · Actualizado el

En esta lección
  1. Leer un error
  2. Capturar errores: try y catch
  3. finally
  4. El objeto error
  5. Lanzar tus propios errores: throw
  6. Cuándo capturar (y cuándo no)
  7. Errores que JavaScript no avisa

Cuando algo sale mal durante la ejecución (acceder a una propiedad de undefined, llamar a algo que no es una función, recibir un JSON mal escrito…), JavaScript lanza una excepción: detiene lo que estaba haciendo y, si nadie la captura, el programa se para y aparece el error en rojo en la consola.

Leer un error

Uncaught TypeError: Cannot read properties of undefined (reading 'nombre')
    at mostrarUsuario (app.js:12:24)
    at app.js:20:1
  • Tipo: TypeError.
  • Mensaje: qué ha pasado. Aquí, que intentaste leer nombre de algo que vale undefined.
  • Traza (stack trace): dónde ha pasado. Archivo app.js, línea 12, columna 24, dentro de la función mostrarUsuario, que fue llamada desde la línea 20.

Aprender a leer los errores es la mitad de programar. Lee siempre el mensaje completo y ve a la línea que indica.

Capturar errores: try y catch

try {
  // código que puede fallar
  const datos = JSON.parse(textoRecibido);
  mostrar(datos);
} catch (error) {
  // qué hacer si falla
  console.log("Los datos recibidos no son válidos:", error.message);
}
  • Se ejecuta el bloque try.
  • Si todo va bien, el catch se salta.
  • Si algo lanza una excepción, el try se interrumpe en ese punto y se ejecuta el catch. El programa sigue después.

finally

El bloque finally se ejecuta siempre, haya error o no. Se usa para “recoger”: cerrar un indicador de carga, liberar un recurso…

mostrarCargando();
try {
  await cargarDatos();
} catch (error) {
  mostrarError("No se pudieron cargar los datos");
} finally {
  ocultarCargando();   // pase lo que pase
}

El objeto error

Los errores que lanza JavaScript son objetos con, al menos, dos propiedades:

  • error.name: el tipo de error.
  • error.message: la descripción.

Los tipos que más verás:

TipoCuándo aparece
ReferenceErrorUsas una variable que no existe (a menudo, una errata)
TypeErrorUsas un valor de forma incorrecta: leer una propiedad de undefined, llamar a algo que no es una función, reasignar una const
SyntaxErrorEl código (o un JSON) está mal escrito
RangeErrorUn número fuera del rango permitido
URIErrorError al codificar o decodificar una URL
ErrorError genérico

Puedes reaccionar de forma distinta según el tipo:

try {
  procesar();
} catch (error) {
  if (error instanceof TypeError) {
    console.log("Dato con formato incorrecto");
  } else {
    throw error;  // no sé qué es: lo vuelvo a lanzar
  }
}

Lanzar tus propios errores: throw

Cuando tu función recibe algo con lo que no puede trabajar, lo correcto es lanzar un error en vez de devolver un valor raro o seguir como si nada:

function calcularEdad(anioNacimiento) {
  if (!Number.isInteger(anioNacimiento)) {
    throw new TypeError("El año de nacimiento debe ser un número entero");
  }
  const actual = new Date().getFullYear();
  if (anioNacimiento > actual) {
    throw new RangeError("El año de nacimiento no puede ser futuro");
  }
  return actual - anioNacimiento;
}

Técnicamente puedes lanzar cualquier cosa (throw "error", throw 42), pero lanza siempre objetos de error (new Error(...), new TypeError(...)): incluyen la traza y se comportan como los errores del propio lenguaje.

Cuándo capturar (y cuándo no)

Los ejemplos de los tutoriales suelen lanzar un error y capturarlo en la misma función. Sirve para aprender la sintaxis, pero en un programa real no tiene sentido: si lo vas a capturar ahí mismo, usa un if.

Lo normal es:

  • La función que detecta el problema lo lanza (throw). No sabe qué hacer con él; solo sabe que no puede continuar.
  • Quien llama a la función, que sí sabe qué hacer, lo captura: mostrar un mensaje al usuario, reintentar, usar un valor por defecto.
  • Si nadie sabe qué hacer, no lo captures: deja que el programa se detenga y el error aparezca en la consola. Es mejor que seguir funcionando con datos incorrectos.

Y un error clásico: capturar y no hacer nada.

try {
  guardar();
} catch (error) {
  // silencio...
}

Así el problema desaparece de la vista, pero sigue ahí. Como mínimo, registra el error con console.error(error).

Errores que JavaScript no avisa

Algunos fallos no lanzan excepción, y por eso son más peligrosos:

  • Leer una propiedad que no existe: usuario.nombr devuelve undefined sin avisar.
  • Operaciones matemáticas imposibles: "hola" * 2 da NaN.
  • Llamar a una función con menos argumentos: los que faltan valen undefined.

Para detectarlos, pon trazas con console.log mientras desarrollas (sobre todo al empezar, aunque todo parezca ir bien) o usa TypeScript, que detecta muchos de ellos antes de ejecutar el código.

Pruébalo tú

Cambia el código y pulsa Ejecutar (o Ctrl + Enter).

excepciones.js
Consola

Pon a prueba lo que has aprendido

[JavaScript] ¿Cuándo se ejecuta el bloque finally?

[JavaScript] Una función recibe un dato con el que no puede trabajar. ¿Qué es lo más correcto?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.