In my recent work related to events and signals, I had a little discussion about errors that are thrown during the dispatch of an event or signal. I did some investigating to see how EventDispatcher handles this and found something rather surprising.

Naturally, I began my search with Adobe’s documentation of dispatchEvent. It is extremely terse:

Dispatches an event into the event flow. The event target is the EventDispatcher object upon which the dispatchEvent() method is called.

Since Adobe is silent on the topic, I made a little test app:

package
{
	import flash.display.*;
	import flash.events.*;
	import flash.utils.*;
	import flash.text.*;
 
	/**
	*   An app to test thrown errors during EventDispatcher's dispatchEvent()
	*   @author Jackson Dunstan
	*/
	public class ErrorDuringDispatchTest extends Sprite
	{
		public function ErrorDuringDispatchTest()
		{
			var logger:TextField = new TextField();
			function log(msg:*): void { logger.appendText(msg + "\n"); }
			logger.autoSize = TextFieldAutoSize.LEFT;
			addChild(logger);
 
			function listenerThrows(ev:Event): void
			{
				log("\tlistenerThrows called");
				throw new Error("listenerThrows error");
			}
 
			function listenerDoesNotThrow(ev:Event): void
			{
				log("\tlistenerDoesNotThrow called");
			}
 
			var ed:EventDispatcher = new EventDispatcher();
			ed.addEventListener("test", listenerThrows);
			ed.addEventListener("test", listenerDoesNotThrow);
 
			log("before dispatching");
			ed.dispatchEvent(new Event("test"));
			log("after dispatching");
		}
	}
}

The output is:

before dispatching
	listenerThrows called
	listenerDoesNotThrow called
after dispatching

This highlights the first interesting aspect of how EventDispatcher dispatches: it recovers from the uncaught errors thrown by its listeners and continues the dispatching unfazed. This is something that TurboSignals (or other signal libraries) could do with a try/catch block, but TurboSignals doesn’t do because of the performance implications. As shown before, the Event/EventDispatcher system is quite slow, so it is entirely possible that it is using a try/catch block (or its equivalent) in the native code implementation.

However, there is a very unusual anomaly that you will notice if you run the above test in a debug version of Flash Player: the thrown error pops up an error dialog! Here is the text:

Error: listenerThrows error
	at ErrorDuringDispatchTest/$construct/listenerThrows()[/Users/jackson/Code/flashtest/ErrorDuringDispatchTest.as:24]
	at flash.events::EventDispatcher/dispatchEventFunction()
	at flash.events::EventDispatcher/dispatchEvent()
	at ErrorDuringDispatchTest()[/Users/jackson/Code/flashtest/ErrorDuringDispatchTest.as:37]

How can EventDispatcher simultaneously catch the error and show the error dialog? The answer seems to lie in the fact that EventDispatcher is implemented in native code and can therefore do things that mere AS3 implementations cannot. So it seems that, at least in one area, EventDispatcher has an unassailable advantage over TurboSignals and similar AS3-based systems. I can see it being a useful notification during development and debugging and useful to continue dispatching during release. How important this is to you is, of course, up to you, but it should be included in any list of pros and cons when deciding on an event/signal system.