Flash listener priorities - depth reincarnated!

Posted: 09/07/09

An image of Flash listener priorities - depth reincarnated!

Listener priorities have the potential to introduce dependencies and smell into your app. There, I said it, but here's why:

As we all know, AS3.0 came with a whole new event model, and our listeners had extra bells and whistles! The majority of the new additions are incredibly useful, like bubbling and weak referencing, whereas the odd one or two are potential gateways for letting those AS2 demons back in!

Consider:

myReference.addEventListener( Event.COMPLETE, onComplete1 );

myReference.addEventListener( Event.COMPLETE, onComplete2, false, 1 );

function onComplete1( e:Event ) :void

{

trace( ‘1' );

}

function onComplete( e:Event ) :void

{

trace( ‘2' );

}

This would trace 2 and then 1, as the higher the priority value assigned to the listener, the higher it's priority when each of the handlers are executed. So the second listener here had a higher priority to the first one (which by default is 0).

In a scenario like this, it seems fairly benign, and unlikely to cause any serious issues (other than a few questions around why the first listener wasn't simply placed after the first, and all of the explicit priorities removed!!) But have a think for a moment how this could start spiralling out of control in a larger system, where a number of objects may assign listeners for an event, and they all declare explicit priorities…

Object 1

myReference.addEventListener( Event.COMPLETE, onComplete2, false, 1 );

Object 2

myReference.addEventListener( Event.COMPLETE, onComplete2, false, 3 );

Object 3

myReference.addEventListener( Event.COMPLETE, onComplete2, false, 2 );

Each object is now trying assert its own importance and priority over the notification of the Event.COMPLETE event, dispatched by myReference. Only the developer of this these 3 objects understands why they must be notified in this order (unless they've written a load of comments explaining it), and modifications to this code now become near impossible without modifying the other listener assignments; causing massive test overhead. Also consider what happens when Mr New Developer walks in and is tasked with writing Object 4, for integration into this system. He might initially assign a regular listener registration, without the priority, but find that because the original developer got into the mindset of Object 3 always needing to do something before Object 2, and Object 1 always doing something last, he now has to go and examine the code for each of these objects before being able to assign a listener priority of 4. Alternatively, he could just assign a priority of 100 to the new listener, as no-one would have got as high as that yet, and it seemed to work just fine… plus “I'm only here to build this part, and don't have the time to understand the dependencies with the other objects. The original developer then comes back to build Object 5, and can't work out why a registration of 5 isn't working, but finds an arbitrary value like 151 seems to do the trick.

See what's happening there? Remember depth 150 or 2364 in AS2, when trying to decide at what depth to add something to the stage? It seems to have reincarnated itself as a listener priority! Now I appreciate that there is a certain degree of developer idiocy going on there too, but I'm sure any developer with a couple of years' experience under their belt will know that it really CAN happen. Give a crappy developer a loop-hole, and they'll gladly go and wrap it around their neck...

Let's be clear, listener registrations to the same object for the same event have a priority set by default - the order by which they were registered. Referring to the example above, assuming objects 1 to 3 were created in that order, their listener registrations would also be assigned in that order. There will be exceptional cases where explicit priority assignment may be useful, and add value to your app (such as stopping further propagation along a chain?); but there will also be a significant number of other occasions where priority meddling will cause big problems and create mighty smelly code. Don't start introducing dependencies between all of your listening objects unless you absolutely see no other way… and even then, I'd try asking a few people what they think first!

Keywords for this post: flash, actionscript 3, listener, priority, event