Excepciones en JavaScript
Javascript, como otros
muchos lenguajes de programación, incluye soporte nativo para el manejo de
excepciones.
Las excepciones, son imprevistos que ocurren durante la ejecución de un
programa; anormalidades que impiden o alteran el comportamiento o flujo normal
de un software.
Su función, es separar el código para el manejo de errores de la lógica de
aplicación del programa. En aquellos lenguajes que incluyen soporte
para el manejo de excepciones, al producirse la anomalidad, se desciende en la
pila de ejecución hasta encontrar un manejador para la excepción, el cual toma
el control en ese momento de la aplicación.
En Javascript, el
manejo de errores puede resultar más necesario que en otros lenguajes debido a
la dificultad natural de este para testear aplicaciones. Por lo general, los
errores en Javascript son crípticos y poco informativos, especialmente en
Internet Explorer. Esto hace interesante el contar con operadores que nos
permitan lanzar nuestros propios mensajes advirtiendo al usuario de que algo ha
ido mal.
Excepciones con Throw
La forma más sencilla
para lanzar errores es utilizando throw. Este comando permite enviar al navegador un evento similar al que se
produce cuando ocurre algún imprevisto o nos encontramos ante un tipo
inesperado de datos. El lenguaje permite enviar todo tipo de
elementos, incluyendo texto, números, valores booleanos o incluso objetos.
Sin embargo, la opción
más usual es enviar el objeto nativo Error:
throw new Error( "Something bad happened." );
Un ejemplo típico de uso es insertarlo como estamento en un condicional:
function mySum(){
var result = 0,
l = arguments.length;
if( l > 10 ) throw console.error( 'Too much
arguments!' );
for( var x = 0; x < l; x++ ){
result
+= arguments[x];
}
return result;
}
console.log( mySum( 3, 4, 34, 5, 7, 8, 1, 32 ) ); // 94
console.log( mySum( 3, 4, 34, 5, 7, 8, 1, 32, 3, 5, 8 ) ); // Error: Too much
arguments
// El
resto del código, será ignorado tras lanzar la excepción...
// ...
// ...
La función anterior suma el valor numérico de los argumentos que le pasemos
pero, si pasamos de un límite (10 en este caso), lanza una excepción abortando
la ejecución.
Es importante tener en
cuenta que throw detiene completamente la ejecución del hilo actual (no sólo el
ámbito o contexto del error), por lo que no el resto del código será
inmediatamente ignorado. Es por ello que se considera una buena
práctica el colocar el estamentothrow al final
del resto de evaluaciones en un condicional:
function checkNumber( my_string ){
var result;
if( my_string < 0 ) result = my_string + ' is a very low Number!';
if( my_string > 1000 ) result = my_string + ' is a very high Number!';
if( parseFloat( my_string ) != my_string ){
err.message = my_string + ' is not a number. ';
throw ( console.error( my_string + ' is not a Number!' ) );
}
result = result || my_string + ' is a correct Number!';
return result;
}
console.log( checkNumber( -17 ) ); // -17 is too low Number!
console.log( checkNumber( '10' ) ); // 10 is a correct Number!
console.log( checkNumber( 1009 ) ); // 1009 is a Number!
console.log( checkNumber( 'no number' ) ); // no number is not a Number!
Excepciones con Try / Catch
Try … Catch corresponde a un tipo de estructura de control Javascript con la que
comprobar el flujo de un programa frente a comportamientos inesperados. La
diferencia entre esta estructura y la anterior es que mientras throw detiene completamente la ejecución, catch realiza una acción determinada frente a los errores para proseguir
después con el flujo definido.
Este tipo de
excepciones se estructuran mediante un bloque de código que evalúa una
condición previa y propone en consecuencia una
ejecución predefinida y otra alternativa frente a anormalidades. La
sintaxis es sencilla y actúa como un condicional más:
function checkPassword( my_string ){
var msg = {};
try {
if( my_string.length < 6 ) throw 'SHORT';
if( my_string.length > 10 ) throw 'LONG';
msg.status = 'Pass Validated';
} catch( err ) {
if( err == 'SHORT' ) msg.status = 'Pass is too short';
if( err == 'LONG' ) msg.status = 'Pass is too long';
} finally {
console.log( 'Password evaluated: ' + msg.status );
}
}
checkPassword( '1234' ); // Password evaluated: Pass is
too short
checkPassword( '12345678901' ); // Password
evaluated: Pass is too long
checkPassword( '12345678' ); // Password
evaluated: Pass Validated
console.log( 'The execution
continues here... ' );
Como podemos
comprobar, la estructura no difiere mucho de la de otros lenguajes como Java: se evalúa un argumento y en caso de no
corresponderse con lo esperado, lanzamos un throw que
captura la cláusula catch. Con el código
de error controlado, podemos proseguir con el flujo normal de la aplicación sin
interrumpirla.
Conclusión
En el desarrollo de software, el manejo de excepciones es una técnica
necesaria para asegurarnos un correcto funcionamiento de nuestras aplicaciones.
En el caso de Javascript, este factor tiene una mayor importancia si cabe dado
que hablamos de un lenguaje donde los errores suelen aparecer de una forma
silenciosa: por lo general, el usuario no se percatará (ni será advertido) de
que algo ha fallado; únicamente la ejecución se detendrá sin más.
Es por esto que las
excepciones, debemos entenderlas como algo más que una herramienta para el
desarrollador.
Tenemos que entender
las excepciones como una metodología más que permite
mejorar la experiencia de usuario y aplicar una capa más de control sobre los
flujos de datos que manejamos.
Usando las estructuras de control que hemos mostrado correctamente, podemos
evitar la aparición de errores incomprensibles (y bloqueantes) perimitiéndonos
reconducir el flujo según lo necesitemos sin deterner el programa.