10.3 Exception Bubbling

 <  Day Day Up  >  

Earlier we learned that exceptions in a try block can be thrown either directly or as the result of a method call. In reality, an exception can be thrown anywhere in an ActionScript program, even on a frame in a timeline! Given that an exception can be thrown anywhere , how does the ActionScript interpreter find the corresponding catch block to handle it? And what if no catch block exists? These mysteries are resolved through the magic of exception bubbling . Let's follow along a bubbly ride with the ActionScript interpreter as it encounters a throw statement in a program. During the following dramatization, the interpreter's musing are shown in code comments.

When a throw statement executes, the interpreter immediately stops normal program flow and looks for an enclosing try block. For example, here's a throw statement:

 // INTERPRETER: Hmm. A throw statement. // Is there an enclosing   try   block for it? throw new Error("Something went wrong"); 

If the throw statement is enclosed in a try block, the interpreter next tries to find a catch block whose parameter's datatype matches the datatype of the value thrown (in the present case, Error ):

 // INTERPRETER: Great, I found a   try   block. Is there a matching   catch   block? try {   throw new Error("Something went wrong"); } 

If a matching catch block is found, the interpreter transfers program control to that block:

 try {   throw new Error("Something went wrong"); // INTERPRETER: Found a   catch   block whose parameter datatype is   Error   ! //              The hunt's over. I'll execute this   catch   block now... } catch (e:Error) {   // Handle problems... } 

But if a matching catch block cannot be found or if the throw statement did not appear within a try block in the first place, then the interpreter checks whether the throw statement occurred within a method or function. If the throw statement occurred in a method or function, the interpreter searches for a try block around the code that invoked the method or function. The following code demonstrates how the interpreter reacts when, within a method, it encounters a throw statement that has no enclosing try block:

 public function doSomething ( ):Void {   // INTERPRETER: Hmm. No   try   block here. I'll check who called this method.   throw new Error("Something went wrong"); } 

If the code that invoked the method or function is enclosed in a try block, the interpreter looks for a matching catch block there and, if it finds a match, executes it. The following code demonstrates an exception thrown out of a method and caught where the method is invoked (i.e., one level up the call stack ).

 class ErrorDemo {   public function doSomething ( ):Void {     // INTERPRETER: Hmm. No try block here.     // I'll check who called this method.     trace("About to throw an exception from doSomething( ) method.");     throw new Error("Something went wrong");   }   public static function startApp ( ):Void {     // INTERPRETER: Aha, here's who called   doSomething( )   . And here's      //              an enclosing   try   block with a   catch   block whose      //              parameter datatype is   Error   ! My work's done.   catch   //              block, please execute now...     try {       var demo:ErrorDemo = new ErrorDemo( );       demo.doSomething( );     } catch (e:Error) {       // Handle problems...       trace("Exception caught in startApp( ), thrown by doSomething( ).");     }   } } 

The call stack is the list of functions and methods currently being executed by the interpreter at any given point in a program. The list includes the functions and methods in the reverse order from which they were called, from top to bottom. When a function is immediately below another function in the call stack, then the lower function was invoked by the higher. The lowest function in the call stack is the function currently executing.


You can use the Flash debugger to view the call stack for the current movie, as described in the Flash authoring tool online Help, under ActionScript Reference Guide Debugging. Note, however, that the Flash debugger displays the currently executing function visually on top rather than on the bottom. That is, the visual display of the call stack in the Flash debugger is the reverse of the call stack discussed in the preceding note. Ultimately, the distinction is arbitrary ”the glass is half full or it's half empty; the stack works top down or bottom up, depending on your point of view.

In the preceding code, an exception thrown by a method was caught by a try/catch block enclosing the method call statement. However, if no try block is found around the function or method caller, the interpreter searches up the entire call stack for a try block with a matching catch block. The following code shows a method throwing an error that is caught two levels up the call stack:

 class ErrorDemo {   public function doSomething ( ):Void {     // INTERPRETER: Hmm. No   try   block here.      // I'll check who called this method.     trace("About to throw an exception from doSomething( ) method.");     throw new Error("Something went wrong");   }   public static function startApp ( ):Void {     // INTERPRETER: Aha, here's who called   doSomething( )   . But still      //              no   try   block here. I'll check who called this method.     var demo:ErrorDemo = new ErrorDemo( );     demo.doSomething( );   } } //   Meanwhile, elsewhere in the program...   // INTERPRETER: Aha! Found a   try   block that has a   catch   block whose //              parameter's datatype is   Error   ! My work's done.   catch   block,  //              please execute now... try {   ErrorDemo.startApp( ); } catch (e:Error) {   // Handle problems...   trace("Exception caught where Error.startApp( ) was invoked."); } 

Notice that the interpreter finds the try/catch block despite the fact that it surrounds not the error-throwing method, nor the caller of the error-throwing method, but the caller of the method that called the error-throwing method!

10.3.1 Uncaught Exceptions

We've seen a number of scenarios in which we've caught (trapped) various errors. But what happens if the interpreter never finds a catch block that can handle the thrown exception? If no eligible catch block is found anywhere in the call stack, then the interpreter:

  • Sends the value of the thrown Error object's message property to the Output panel (or simply sends the thrown expression itself if it wasn't an Error object)

  • Aborts execution of all code currently remaining in the call stack (including frame scripts and callback functions such as a setInterval( ) callback)

Execution of the program then resumes normally. For example, if an uncaught exception occurs on frame 1, layer 1 of a movie, the code on frame 2 executes normally. In fact, code on frame 1, layer 2 will also execute normally. For frame-based code, only the specific frame script that generated the uncaught exception is aborted.

The following code demonstrates a method that throws an error that is never caught:

 class ErrorDemo {   public function doSomething ( ):Void {     // INTERPRETER: Hmm. No   try   block here.     // I'll check who called this method.     throw new Error("Something went wrong");   }   public static function startApp ( ):Void {     // INTERPRETER: Aha, here's who called   doSomething( )   . But still     // no   try   block here. I'll check who called this method.     doSomething( );   } } //   Meanwhile, elsewhere in the program...   // INTERPRETER: Hmm. Well, I searched all the way to the top, and still  //              no   try   block. I'll send "Something went wrong" to the Output  //              panel. Maybe the programmer will know what to do. ErrorDemo.startApp( ); 

As we've just seen, because exceptions bubble up the call stack, it's not necessary for a method to catch its own exceptions. And it's not even necessary for the caller of a method to catch its exceptions. The exception can legally be caught at any level in the call stack. Any method can delegate exception handling to the code that calls it. That said, it's bad form and harmful to a program to throw an exception and then never catch it. You should always catch exceptions or, having encountered an uncaught exception, revise your code so that the exception isn't thrown in the first place.

Unfortunately, there's no way in ActionScript to tell the compiler to force a program to catch its own exceptions. As we'll learn later, ActionScript does not support Java-style checked exceptions , which are exceptions that must be caught in order for a program to compile. In Java terminology, all exceptions in ActionScript are unchecked.

 <  Day Day Up  >  


Essential ActionScript 2.0
Essential ActionScript 2.0
ISBN: 0596006527
EAN: 2147483647
Year: 2004
Pages: 177
Authors: Colin Moock

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