Async APIs and Anonymous Functions

ActionScript has a nifty feature called anonymous functions that is often handy when working with asynchronous APIs. Here’s how it works:

var t:Timer = new Timer( 0 );
var message:String = “Hello, World!”;
t.addEventListener( TimerEvent.TIMER_COMPLETE, function( evt:Event ):void { trace( message ); });

Here, function creates a new, anonymous function taking one argument (an event) and with the body specified inline. I don’t recommend using this technique for long event handler functions; those are usually easier to write as callback functions. But this is a great technique to use when your callback function is short. Replacing a whole set of short callback functions with anonymous functions is a great code cleanup.

Note in the example above that the function body is able to reference message, which is a variable that was defined back in the code that created this function. Creating an anonymous function creates a closure that captures the in-scope variables visible where the function is defined and makes them available when the function executes. This saves you the trouble of littering your class with member variables that exist just to remember stuff until an event handler gets called. Another great code cleanup.

This wraps it up for the basic techniques for asynchronous programming. Next we’ll start in on more advanced topics.

10 Responses to Async APIs and Anonymous Functions

  1. g10 says:

    question: are you able to remove such an anonymous function from the eventListener list in as3?eg. witht.removeEventListener( TimerEvent.TIMER_COMPLETE, function( evt:Event ):void { trace( message ); });why I’m asking: in as2 you typically ended up passing anonymous function to listeners by using the Delegate class (who creates anonymous functions, fortunatly not needed anymore in as3), with the downside that it was impossible to remove them at a later moment!

  2. Oliver Goldman says:

    Good question. You can only remove an anonymous function if you keep another reference to it, as removal is done by checking strict equality (===). The example in your comment wouldn’t work because it would create a new anonymous function that was not a listener.

  3. keith says:

    Hi oliver, I just came across your post while Googling.I am trying to removeEventListener for an anonymous function, and reference it through a class var, but it isn’t working. Your comment says this is possible, but I sure can’t figure it out. I’d really appreciate your help! Here’s my code:private static var _myFunc:Function;clip.addEventListener(“rollOver”,_myFunc = function():voidtrace(“yay!”);});clip.removeEventListener(“rollOver”, _myFunc);

  4. Oliver Goldman says:

    It’s not obvious to me without a complete sample why what you’re trying isn’t working. (Your anonymous function should be taking an event as an argument, but omitting that will only prevent it from getting called–not registered.)Once you bother to save off the anonymous function in a variable, however, you might as well use a regular function definition.

  5. Kenneth E. says:

    Can you make the anonymous function typed, equivalent to a .net delegate?

  6. Oliver Goldman says:

    I don’t know much about .NET delegates, so I’m not sure I can give a useful answer to your question. Perhaps someone more knowledge will chime in.The anonymous function itself is typed in the same way as any ActionScript function is.However, ActionScript does not perform type-checking on the function provided as an argument to the addEventListener() call. It is possible to pass in a function that, for example, takes the wrong number or type of arguments. This is the same whether or not an anonymous function is used. These errors are caught at run-time, not compile-time.More generally, delegates serve the same basic purpose as the ActionScript listener/event model but go about it in a slight different way.

  7. amarghosh says:

    you can remove anonymous listeners without having to store them in local variables.use arguments.calleei found it in this blog

  8. Travis Parker says:

    Anonymous functions in AS3 suffer an unfortunate problem that they didn’t in AS2 – they don’t get their own scope like they should. Let me give an example:(function(){var str:String = “I am broken”;})();trace(str);The ‘var’ statement inside the anonymous function bled out into the surrounding scope.This bites you when you want to use a short sweet variable name inside event handlers:stage.addEventListener(“nosuchevent”, function() { var a:String = “”; });stage.addEventListener(“anotherbadevent”, function() { var a:uint = 4; });The above is written properly given the scoping rules, but the compiler complains that you are trying to redeclare a variable!

  9. ryan says:

    i used an event closure within a static method like this:public static function gotoAndPlayDelay(movie : MovieClip, frame : int, delaySeconds : Number = 0) : void {var delay : Timer = new Timer(delaySeconds * 1000, 1);var delayCompleteListener : Function = function(event : TimerEvent) : void {delay.removeEventListener(TimerEvent.TIMER_COMPLETE, delayCompleteListener);movie.gotoAndPlay(frame);delay = null;};delay.addEventListener(TimerEvent.TIMER_COMPLETE, delayCompleteListener);delay.start();}notice how i cleanup on the timer’s complete event.

  10. ryan says:

    also make a note that you cannot use a weakReference to you event listener… it has to be strong otherwise it will not execute…just make sure to perform all your cleanup code…