No matter how careful you are when developing your applications, there will be times when run-time errors will occur. You might make a mistake in development, or perhaps users will use your application in a way that you never anticipated. It is considered a poor practice to allow those errors to be seen by users. Instead, you should anticipate where a run-time error could occur and handle those using TRy-catch statements. Run-time errors, also called exceptions, can be caught, and you can choose what should happendepending on the type of exception caught and the situation. Exception handling gives your applications the chance to recover gracefully from run-time errors instead of having the user have the error pop up when using your application. The new ActionScript 3.0 compiler reports syntactical errors to you in Flex Builder and prevents your application from being built. These types of errors are not the type to be dealt with using try-catch. Run-time errors occur when a user is running your application and represent errors caused during playback of the SWF file. In earlier versions of Flash Player, more often than not, Flash Player failed silently. This was not a good situation for you as the developer because you were not given a clue about why the application did not work, you just knew it did not. So run-time errors are a good thing for you as a developer, but you should not let the users of the application see them. Using the try-catch SyntaxThe general syntax for using TRy-catch is the following: try{ //possible error producing code; } catch (e:ErrorType){ //code to execute when error is caught; } A simple example designed to guarantee an error is as follows: <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; private var newAC:ArrayCollection=new ArrayCollection(); private function test():void{ try{ var myVar:Object=newAC.getItemAt(10); } catch (e:Error){ errorLabel.text="error caught"; } } ]]> </mx:Script> <mx:Label text="error Label"/> <mx:Button label="Cause a Problem" click="test()"/> In this case, when the Button is clicked, the Label would display error caught, and no exception error would be displayed in the browser running the application. You can also access properties and methods of the error object, stored in the e variable in the previous code example, in the catch statement. Those available properties and methods are as follows:
By using the trace() statement in the catch block, you can see what appears in the Console view for each property and method: catch (e:Error){ trace(e.message); trace(e.name); trace(e.getStackTrace()); trace(e.toString()); } Note
Understanding the Error TypesSo far, both code examples use the Error class, which is the base class for all error classes in ActionScript. There are number of error classes. One set is defined by ECMAScript, and the others are ActionScript specific:
Using Multiple catch BlocksYou can use these error types with a single catch block or you can have multiple catch blocks associated with a single TRy statement. So if you have a piece of code that might throw different kinds of errors, and you want to handle the different errors with different code, you can use multiple catch blocks. Here are some rules to remember it you are doing this:
Here are a few examples to further clarify the rules to remember: Example Using Only One catch Block<mx:Script> <![CDATA[ import mx.collections.ArrayCollection; private var newAC:ArrayCollection=new ArrayCollection(); private function test():void{ try{ var myVar:Object=newAC.getItemAt(10); } catch (e:EvalError){ errorLabel.text="EvalError class"; } catch (e:RangeError){ errorLabel.text="RangeError class"; } catch (e:Error){ errorLabel.text="Error base class"; } } ]]> </mx:Script> <mx:Label text="error Label"/> <mx:Button label="Cause a Problem" click="test()"/> When the Button is clicked, the Label would display the RangeError class. The code in the TRy block would cause the error. The first catch block is looking for an EvalError, which would not be a match so processing would continue. The second catch block is a RangeError, which is a match, so the corresponding string would be displayed. The third catch block with the base Error class is also a match, but because a previous catch block was used, the Error catch block is skipped. Example Showing Bad Practice of Using the Error Base Class in the First catch Block<mx:Script> <![CDATA[ import mx.collections.ArrayCollection; private var newAC:ArrayCollection=new ArrayCollection(); private function test():void{ try{ var myVar:Object=newAC.getItemAt(10); } catch (e:Error){ errorLabel.text="Error base class"; } catch (e:EvalError){ errorLabel.text="EvalError class"; } catch (e:RangeError){ errorLabel.text="RangeError class"; } } ]]> </mx:Script> <mx:Label text="error Label"/> <mx:Button label="Cause a Problem" click="test()"/> When testing this code, the Label would display the Error base class. The code in the TRy block would cause the error. The first catch block is looking for the Error base class, which would match any kind of error, so the corresponding string would be displayed. Because the first catch block is executed, the second and third catch blocks are ignored. This demonstrates the rule that you should never place a catch block with the type Error before other catch blocks. In this example, the specific error type, RangeError, was used to show that it was never evaluated because of order of the catch blocks. Using the finally StatementActionScript, like many languages that implement some kind of try-catch syntax, offers a finally statement. The finally statement should be placed after all of your catch blocks, and the code it contains will be executed whether an error occurs in the try statement or not. In the example code shown, the errorLabel would display the RangeError class, and the finallyLabel would display "finally executed". <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; private var newAC:ArrayCollection=new ArrayCollection(); private function test():void{ try{ var myVar:Object=newAC.getItemAt(10); } catch (e:RangeError){ errorLabel.text="RangeError class"; } finally{ finallyLabel.text="finally executed"; } } ]]> </mx:Script> <mx:Label text="error Label"/> <mx:Label text="finally Label"/> <mx:Button label="Cause a Problem" click="test()"/> In this example, even if you commented the assignment statement in the try statement, and no error occurred, the finally statement would still be executed, and the finallyLabel would display the corresponding text. Using the throw StatementThere might be times when you want to manually generate an error. This means that something has occurred in your application that although it is not a run-time error, you want to raise an exception so it can be handled in your normal exception handling scheme. For instance, you might have a situation in which the number of products ordered is less than those in stock. You could programmatically take care of the situation, but might also want to handle the problem by raising an exception. One approach would be to use an existing error class and put in a message you could later examine to check what the error was. In the following code example, in the try statement the throw statement is used to raise an exception of type Error, and the error is then caught and the custom message is displayed. <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; private var newAC:ArrayCollection=new ArrayCollection(); private function test():void{ try{ throw new Error("This is a custom message on a throw statement"); } catch (e:Error){ errorLabel.text=e.message; } } ]]> </mx:Script> <mx:Label text="error Label"/> <mx:Button label="Cause a Problem" click="test()"/> In this code example the errorLabel would display "This is a custom message on a throw statement". Creating Your Own Error ClassesWhen wanting to throw an error, the next step would be to throw an error of a class you have created. Perhaps you will look for that specific class in your catch and/or it will contain a special code to alert you of a particular exception. The following ActionScript class defines a custom error class that extends the base Error class. You add an instance variable named customCode that will hold the error code that will be generated in a specific situation you have defined. By the package name, errorClasses, you see that this class was saved in a directory named errorClasses. package errorClasses { public class CustomError extends Error { public var customCode:int; public function CustomError(message:String,customCode:int){ super(message); this.customCode=customCode; }//end constructor }//end class }//end package To use this custom class, you'll need to import the class and then throw it when a certain condition occurs. When you instantiate it, you'll need to pass both a custom message as the first parameter and a custom integer code as a second parameter. The following code example shows just that: <mx:Script> <![CDATA[ import errorClasses.CustomError; private function test():void{ try{ throw new CustomError("Custom message",123); } catch (e:CustomError){ errorLabel.text=e.message; codeLabel.text=String(e.customCode); } } ]]> </mx:Script> <mx:Label text="error Label"/> <mx:Label text="code Label"/> <mx:Button label="Cause a Problem" click="test()"/> When the Button is clicked, the errorLabel displays "Custom message", and the codeLabel displays 123, both of which are arbitrary example values. Note
|