Gestión de errores sincrónicos en una aplicación

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

La gestión de errores más habitual hace referencia a la lógica de gestión de errores sincrónicos, en la que se insertan sentencias en el código para capturar errores sincrónicos mientras se ejecuta una aplicación. El tipo de gestión de errores permite que la aplicación observe los errores en tiempo de ejecución y se recupere cuando fallen las funciones. La lógica para capturar un error sincrónico incluye sentencias try..catch..finally , que literalmente intentan una operación, capturan cualquier respuesta de error del motor de ejecución de Flash y finalmente ejecutan alguna otra operación para administrar la operación fallida.

Uso de sentencias try..catch..finally, sentencias

Cuando trabaje con errores en tiempo de ejecución sincrónicos, utilice sentencias try..catch..finally para capturar errores. Si se produce un error de tiempo de ejecución, el motor de ejecución de Flash genera una excepción, lo que significa que se suspende la ejecución normal y se crea un objeto especial de tipo Error. El objeto Error se genera en el primer bloque catch disponible.

La sentencia try incluye sentencias que podrían provocar errores. La sentencia catch siempre se debe utilizar con una sentencia try . Si se detecta un error en una de las sentencias del bloque try , se ejecutarán las sentencias catch asociadas a la sentencia try .

La sentencia finally incluye sentencias que se ejecutarán independientemente de que se produzcan errores en el bloque try . Si no hay errores, las sentencias del bloque finally se ejecutarán una vez que hayan finalizado las sentencias del bloque try . Si se producen errores, primero se ejecutará la sentencia catch correspondiente, seguida de las instancias del bloque finally .

El código siguiente muestra la sintaxis necesaria para usar las sentencias try..catch..finally :

try 
{ 
    // some code that could throw an error 
} 
catch (err:Error) 
{ 
    // code to react to the error 
} 
finally 
{ 
    // Code that runs whether an error was thrown. This code can clean 
    // up after the error, or take steps to keep the application running. 
}

Cada sentencia catch identifica el tipo de excepción específico que gestiona. La sentencia catch puede especificar solo clases de errores que son subclases de la clase Error. Cada sentencia catch se comprueba por orden. Solo se ejecutará la primera sentencia catch que coincida con el tipo de error generado. Dicho de otra forma, si primero se comprueba la clase Error de nivel superior y luego la subclase de la clase Error, únicamente coincidirá la clase Error de nivel superior. En el código siguiente se muestra este escenario:

try 
{ 
    throw new ArgumentError("I am an ArgumentError"); 
} 
catch (error:Error) 
{ 
    trace("<Error> " + error.message); 
} 
catch (error:ArgumentError) 
{ 
    trace("<ArgumentError> " + error.message); 
}

El código anterior muestra el resultado siguiente:

<Error> I am an ArgumentError

Para capturar correctamente la clase de error ArgumentError, es necesario asegurarse de que los tipos de error más específicos se enumeran primero, y que los más genéricos aparecen después, tal como se muestra en el código siguiente:

try 
{ 
    throw new ArgumentError("I am an ArgumentError"); 
} 
catch (error:ArgumentError) 
{ 
    trace("<ArgumentError> " + error.message); 
} 
catch (error:Error) 
{ 
    trace("<Error> " + error.message); 
}

Varios métodos y propiedades de la API de ActionScript generan errores en tiempo de ejecución si detectan errores durante la ejecución. Por ejemplo, el método close() de la clase Sound genera un error IOError si no puede cerrar el flujo de audio, tal como se muestra en el código siguiente:

var mySound:Sound = new Sound(); 
try 
{ 
    mySound.close(); 
} 
catch (error:IOError) 
{ 
    // Error #2029: This URLStream object does not have an open stream. 
}

A medida que el usuario se familiarice con Referencia de ActionScript 3.0 para la plataforma de Adobe Flash , reconocerá los métodos que generan excepciones, tal y como se indica en la descripción de cada método.

La sentencia throw

Los motores de ejecución de Flash generan excepciones cuando localizan errores en la aplicación que se está ejecutando. Asimismo, se pueden generar excepciones explícitamente mediante la sentencia throw . Si se generan errores de forma explícita, Adobe recomienda generar instancias de la clase Error o sus subclases. En el código siguiente se muestra una sentencia throw que genera una instancia de la clase Error, MyErr , y que termina por llamar a la función myFunction() como respuesta tras la generación del error:

var MyError:Error = new Error("Encountered an error with the numUsers value", 99); 
var numUsers:uint = 0; 
try 
{ 
    if (numUsers == 0) 
    { 
        trace("numUsers equals 0"); 
    } 
} 
catch (error:uint) 
{ 
    throw MyError; // Catch unsigned integer errors. 
} 
catch (error:int) 
{ 
    throw MyError; // Catch integer errors. 
} 
catch (error:Number) 
{ 
    throw MyError; // Catch number errors. 
} 
catch (error:*) 
{ 
    throw MyError; // Catch any other error. 
} 
finally  
{ 
    myFunction(); // Perform any necessary cleanup here. 
}

Debe tenerse en cuenta que las sentencias catch se ordenan de manera que los tipos de datos más específicos se muestren en primer lugar. Si la sentencia catch del tipo de datos Number se muestra primero, las sentencias catch de los tipos de datos uint e int nunca se ejecutarán.

Nota: en el lenguaje de programación Java, cada función que puede generar una excepción debe declararlo y enumerar las clases de excepción generables en una cláusula throws asociada a la declaración de la función. ActionScript no requiere la declaración de las excepciones que puede generar una función.

Visualización de un mensaje de error simple

Una de las mayores ventajas del nuevo modelo de eventos de error y excepción radica en que permite indicar a los usuarios cuándo y por qué falla una acción. La parte del usuario consiste en escribir el código para que se muestre el mensaje y se ofrezcan opciones a modo de respuesta.

El siguiente código incluye una sencilla sentencia try..catch para mostrar el error en un campo de texto:

package 
{ 
    import flash.display.Sprite; 
    import flash.text.TextField; 
     
    public class SimpleError extends Sprite 
    { 
        public var employee:XML =  
            <EmpCode> 
                <costCenter>1234</costCenter> 
                <costCenter>1-234</costCenter> 
            </EmpCode>; 
 
        public function SimpleError() 
        { 
            try 
            { 
                if (employee.costCenter.length() != 1) 
                { 
                    throw new Error("Error, employee must have exactly one cost center assigned."); 
                } 
            }  
            catch (error:Error) 
            { 
                var errorMessage:TextField = new TextField(); 
                errorMessage.autoSize = TextFieldAutoSize.LEFT; 
                errorMessage.textColor = 0xFF0000; 
                errorMessage.text = error.message; 
                addChild(errorMessage); 
            } 
        } 
    } 
}

Al usar una mayor gama de clases de error y errores de compilador incorporados, ActionScript 3.0 proporciona más información que las versiones anteriores acerca del motivo por el que falla algo. Esta información permite crear aplicaciones más estables con una mejor gestión de errores.

Regeneración de errores

Al crear aplicaciones, pueden existir varias circunstancias en las que sea necesario volver a generar un error, si este no consigue gestionarse adecuadamente. Por ejemplo, el siguiente código muestra un bloque anidado try..catch , que regenera un error de tipo ApplicationError personalizado si el bloque anidado catch no puede gestionar el error:

try 
{ 
    try 
    { 
        trace("<< try >>"); 
        throw new ApplicationError("some error which will be rethrown"); 
    } 
    catch (error:ApplicationError) 
    { 
        trace("<< catch >> " + error); 
        trace("<< throw >>"); 
        throw error; 
    } 
    catch (error:Error) 
    { 
        trace("<< Error >> " + error); 
    } 
} 
catch (error:ApplicationError) 
{ 
    trace("<< catch >> " + error); 
}

La salida del fragmento anterior será de esta forma:

<< try >> 
<< catch >> ApplicationError: some error which will be rethrown 
<< throw >> 
<< catch >> ApplicationError: some error which will be rethrown

El bloque try anidado genera un error ApplicationError personalizado que captura el bloque catch posterior. Este bloque catch anidado puede intentar gestionar el error y, si no lo consigue, puede generar el objeto ApplicationError en el bloque try..catch en el que está contenido.