Handling Errors with try-catch


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 Syntax

The 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:

  • message(property) Contains the message associated with the Error object.

  • name(property) Contains the name of the Error object.

  • getStackTrace()(method) For debugger versions of the Flash Player, only; this method returns the call stack for an error as a string at the time of the error's construction.

  • toString()(method) Returns the string "Error" by default or the value contained in Error.message, if defined.

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

Remember that when using the trace() statement you must Debug, not Run, your application to see the results in the Console view.


Understanding the Error Types

So 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:

ECMAScript Errors

ActionScript Specific Errors

Error

ArgumentError

EvalError

SecurityError

RangeError

VerifyError

ReferenceError

EOFError

SyntaxError

IllegalOperationError

TypeError

IOError

URIError

MemoryError

 

ScriptTimeOutError

 

StackOverFlowError


Using Multiple catch Blocks

You 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:

  • The first catch block with a matching error type will be executed.

  • Only one catch block will be executed.

  • Never place a catch block with the type Error before other catch blocks. Because Error will match all errors, you guarantee that the other catch blocks will never be used.

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 Statement

ActionScript, 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 Statement

There 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 Classes

When 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

Because of security constraints, users of Microsoft Internet Explorer cannot build and preview this next task. History Management is used and does not work in Internet Explorer when previewing a local file, meaning that it does not work when previewing local files on your hard drive. However, it will work if the file is on a web server or accessed through an HTTP URL as opposed to the file:// URL that is used during normal development. If you are using Internet Explorer, you will need to preview these files from a web server. History Management does work in Firefox and Netscape browsers when previewing a local file.


1.

From the FlexGrocer project, open the file as/ecomm.as. Locate the displayProdByCategory() method and remove all if statement logic so it appears as follows:

private function displayProdByCategory(event:CategoryEvent):void{    prodTile.visible=false;    var prodArray:Array=catProds.getProdsForCat(event.cat.catID);    prodByCategory=new ArrayCollection(prodArray);    prodTile.visible=true; } 


You are removing the logic that prevents a run-time error from occurring. You will replace the if logic with try-catch-finally.

2.

Run the EComm.mxml application. Click one of the categories, and then click the browser's Back button to get the run-time error to appear.

3.

In the function, surround the four lines of code with a TRy block; then trace the message property of the error in a catch block. Debug the application. Click one of the categories and then click the browser's Back button.

private function displayProdByCategory(event:CategoryEvent):void{    try{      prodTile.visible=false;      var prodArray:Array=catProds.getProdsForCat(event.cat.catID);      prodByCategory=new ArrayCollection(prodArray);      prodTile.visible=true;    }catch(e:Error){      trace(e.message);    } } 


You should see in the Console view that the trace statement displays the same message as in the first line of the run-time error.

4.

Remove the trace statement.

Even though the trace statement will display only information when debugging an application, there is no need to leave the code in the function.

5.

Move the code that sets the prodTile's visible property to false above the try block. Just below this line of code, create a variable local to the function named prodArray and data type it as Array. Alter the existing code, as shown in the following example, and implement the logic of the try-catch-finally code with the newly created prodArray variable.

private function displayProdByCategory(event:CategoryEvent):void{    prodTile.visible=false;    var prodArray:Array;    try{       prodArray=catProds.getProdsForCat(event.cat.catID);    }catch( err:Error ){       prodArray=new Array();    }finally{       prodByCategory=new ArrayCollection(prodArray);    }    prodTile.visible=true; } 


This will catch the error and just set the ArrayCollection to an empty array if the user presses the back button too many times. So, instead of an error being thrown and the application crashing, the application is ready to use.

6.

Save ecomm.as and run the Ecomm.mxml application. Click one of the categories and then click the browser's back button.

Rather than an error being displayed, the area below the toolbar is blank.




Adobe Flex 2.Training from the Source
Adobe Flex 2: Training from the Source
ISBN: 032142316X
EAN: 2147483647
Year: 2006
Pages: 225

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net