A different view on loops – listener-looping

What is the usual practice when searching / setting / operating over some list of item? I think you usually think of iterating over some list (array) or linked list etc. Well, ActionScript has to offer one more technique you maybe never tought of, lets call it listener-looping. ActionScript is event based language, that means that every EventDispatcher based classes are able to listen and dispatch events. And this fits our needs for loop alternative. Lets suggest, you do not have any list to be iterated over but you still have a chance to accomplish it by making each item listening for custom event.

Here is a simple example code for counting all listening items and performing search over items.

package
{
    import flash.display.Sprite;
    
    public class TestAS extends Sprite
    {
        public function TestAS()
        {
            for(var i:uint = 0; i < 5; i++)
                new Item(i, this);
                
            var event:CustomEvent;
            
            event = new CustomEvent(CustomEvent.COUNT)
            dispatchEvent(event);
            trace("count:", event.count);
            
            event = new CustomEvent(CustomEvent.FIND)
            event.position = 2;
            dispatchEvent(event);
            trace("find position:", event.result.position);
        }
    }
}

import flash.events.EventDispatcher;
import flash.events.Event;

class Item extends Object
{
    public var position:uint;
    private var dispatcher:EventDispatcher;
    
    public function Item(position:uint, dispatcher:EventDispatcher):void
    {
        this.position = position;
        this.dispatcher = dispatcher;
        
        dispatcher.addEventListener(CustomEvent.COUNT, count);
        dispatcher.addEventListener(CustomEvent.FIND, find);
    }
    
    private function count(event:CustomEvent):void
    {
        event.count++;
    }
    
    private function find(event:CustomEvent):void
    {
        if(event.position != position)
            return;
            
        event.result = this;
        event.stopImmediatePropagation();
    }
}

class CustomEvent extends Event
{
    public static const COUNT:String = "CustomEventCOUNT";
    public static const FIND:String = "CustomEventFIND";
    
    public var count:uint = 0;
    public var position:uint;
    public var result:Item;
    
    public function CustomEvent(type:String, bubbless:Boolean = false, 
        cancelable:Boolean = false):void
    {
        super(type, bubbless, cancelable);
    }
}

returns:

count: 5
find position: 2

What is happening here let us better understand event livecycle:

  1. Event instance is created
  2. Event is dispatched
    • every Item catches dispatched Event synchronously after dispatching (Event passed as reference)
    • Event reference is being modified, or may be even stopped (stopImmediatePropagation() method)
    • all listeners executed one by one (until stopped)
  3. Event reference is used as result holder

Now you may wonder how fast it is. Here is the app comparing speed of listener-looping vs. linked list:

Results may vary…

--- Starting Linked List test --- (500000 iterations)
testLinkedExe: 16 ms.

--- Starting Events test --- (500000 iterations)
testEventsExe: 109 ms.

… but listener-looping are slower than linked lists (+400% up to +1000%).

Leave a comment

Please be polite and on topic. Your e-mail will never be published.