Copyright © 2004 O'Reilly Media, Inc. All Rights Reserved.
Essential ActionScript 2.0
By Colin Moock
June 2004
ISBN: 0-596-00652-7
More info... .
Available from booksellers or direct from O'Reilly Media, www.oreilly.com.

Cover image
This content is excerpted from the above-named O'Reilly publication, with permission, by agreement with ActionScript.org.

Earlier we learned that finally executes no matter what happens in a try block. In theory, that should be true. However, a bug in Flash Player 7 prevents finally from executing when a nested try/catch/finally statement returns from a function, as shown in the following code:

function nestedFinallyBugDemo ( ):Void {
  try {
    try {
      throw new Error("Test error");
    } finally {
      trace("Inner finally block.");
      return;
    }
  } finally {
    trace("Outer finally block.");  // Due to a bug in Flash Player 7,
                                    // this line never executes.
  }
}
nestedFinallyBugDemo( );


// Displays:
Inner finally block.

The need for this structure is rare, so you probably won't encounter the bug, and Macromedia may very well fix it in Flash Player 8 if not an interim version of Flash Player 7.

Control Flow Changes in try/catch/finally

As we've seen throughout this chapter, the throw statement changes the flow of a program. When the interpreter encounters a throw statement, it immediately stops what it's doing and transfers program control to eligible catch and finally blocks. However, it is also quite legal for those catch and finally blocks to change program flow again via return (in the case of a method or function) or break or continue (in the case of a loop). Furthermore, a return, break , or continue statement can also appear in a try block.

To learn the rules of flow changes in the try/catch/finally statement, let's look at how the return statement affects program flow in a try, catch, and finally block. The following code examples contain a method, changeFlow( ) that demonstrates a control flow in various hypothetical situations. Note that, in all cases, the behavior of the changeFlow( ) method would be the same if it were a standalone function.

Example 10-1 shows a return statement in a try block, placed before an error is thrown. In this case, the method returns normally, and no error is ever thrown or handled. However, before the method returns, the finally block is executed. Note that you're unlikely to see code exactly like Example 10-1 in the real world. In most applied cases, the return statement would occur in a conditional statement and execute in response to some specific condition in the program.

Example 10-1. Using return in try, before throw

function changeFlow ( ):Void {
  try {
    return;
    throw new Error("Test error.");
  } catch (e:Error) {
    trace("Caught: " + e);
  } finally {
    trace("Finally executed.");
  }
  trace("Last line of method.");
}


// Output when changeFlow( ) is invoked:
Finally executed.

Example 10-2 shows a return statement in a try block, placed after an error is thrown. In this case, the return statement is never executed because an error is thrown before it is reached. Once the error is caught and the try/catch/finally completes, execution resumes after the try/catch/finally statement, and the method exits at the end of the method body. Again, Example 10-2 demonstrates a principle but is atypical of real-world code, which would normally throw the error based on some condition.