AS3 Signals Tutorial

Thursday, January 21st, 2010 | ActionScript 3, tutorials, videos

AS3 Signals is an awesome open-source project created by Robert Penner that will make you re-think the way you approach events in all of your future projects. I put together this video tutorial (mostly to force myself to learn it) and I’ve been REALLY impressed with it so far. Go ahead and give it a watch:


Watch the Intro to AS3 Signals Video Tutorial

Click to view the video in a pop-up. Right-click and “save as” to download the video to your hard drive.

For more info on AS3 Signals, check out http://wiki.github.com/robertpenner/as3-signals/ and join the google group.

Download the swc: as3-signals.swc

*note – I just realized that I said, “it’s really, really easy and it’s also really simple” during the video. That’s really just a testament to how easy it is ;)

*second note – thanks for all the votes on video resolution preferences. I’ll be sticking with 1024×768 from here on out.

  • Nicole Chung
    This is great! I have used signals for a small project and already it has saved a LOT of typing.
    That being said, how do you use Native Signals to dispatch value objects?? I see that it's available but I don't quite get how to use it...will there be a tutorial part 2 soon?
  • Native Signals have to dispatch Events.
  • Scott
    Thanks for the great tutorial!
  • misha72
    @robert
    First, thanks for sharing your work!

    One thing I am looking for is a "atOnceListener" which will also called even U added him after the dispatch().
    U know, sometimes is hard to handle the order of all. So every time I have to ask if the event is called before.
    I know I have to check this with controllers , but in big projects....


    For example, now it looks like:

    if(myModel.hasDispatched_Finished) // the model has to memory this status
    {
    createMyStuff();
    }
    else
    {
    myModel.finished.add(createMyStuff)
    }
    private function createMyStuff():void
    {
    //creating stuff with the myModel.data ...
    }


    It would be great to have something like:
    myModel.finished.addSemaphoreOnce(createMyStuff); // == will call createMyStuff immediately if dispatched before (once)
    myModel.finished.addSemaphore(createMyStuff);// == will call createMyStuff immediately if dispatched before (and after)


    Maybe other Objects should be able to add Listeners without the memory factor.
  • Interesting... it doesn't seem like a common-enough use case for me to add it, but you can take the code and extend it yourself.
  • misha72
    yes, I will do it.
  • mark
    Hi, just to let you know if you click on the image it loads the wrong tutorial - installing Haxe tutorial.
    Thanks
  • johnlindquist
    Thanks, fixed it.
  • P48l0
    this stuff sounds interesting, i will read more about this.
  • This is very cool. God bless you for trimming "addEventListener" back down to "add". A thought though - NativeSignals still seem to be quite verbose in taking 3 arguments. It would be nice if we had a series of constants that acted as shortcuts to a subset of the most popular AS3 event constants so we could do something like Signal.CLICKED or Signal.TIMER instead of MouseEvent.CLICKED et al. I'd imagine this could eliminate the need for the third argument in a NativeSignal which seems redundant at first glance.

    new NativeSignal(this, NativeSignal.CLICKED);

    would be so much nicer.

    Great work nonetheless. Looking forward to trying this out on my next project.

    Cheers,
    Stephen
  • John Lindquist
    I believe the third parameter is optional, so you can just write NativeSignal(this, MouseEvent.CLICK);
  • Karl Knocking
    I understand that the signals are better for creating your own Events.
    But can someone explain the advantage of using signals instead of writing:
    john.addEventListener(MouseEvent.CLICK, cl_john);
    function cl_john(evt:MouseEvent){
    }

    To me it looks like less code?!
  • thanks for the tutorial John.
    you got me hooked to AS3 signals
  • I really like the idea of ditching events for a cleaner, more manageable system. But how robust is it? Would you recommend using and relying on it in client projects in it's current state?
    I've noticed that all of the examples (I've seen so far) show the use of a public property for a signal. Would this not be better as a public getter? This would mean that at no point could the signal be replaced with another one, leaving the old one to run around in memory with references to listeners.
    Did you choose not to use Vectors to store the listeners (opposed to Arrays), for compatibility with FP9, or have you found them to be better for performance?
    Keep up the good work!

    P.S. Good tutorial! :)
  • @Mark:

    > But how robust is it? Would you recommend using and
    > relying on it in client projects in it’s current state?

    I consider the Signal class well-covered by unit tests, and I'm using it in my main project. DeluxeSignal is more experimental. I have a lot of unit tests for it, many of which are nearly identical to the Signal tests. But I haven't used DeluxeSignal in real projects.


    > I’ve noticed that all of the examples (I’ve seen so far) show the use
    > of a public property for a signal. Would this not be better as a
    > public getter?

    I kept my wiki examples simple. But in my real code, I make Signals read-only with getters. I use the same style as Richard Lord in his SmartySignals example:

    http://www.richardlord.net/blog/flexcaster-smar...


    > Did you choose not to use Vectors to store the listeners (opposed to
    > Arrays), for compatibility with FP9, or have you found them to be
    > better for performance?

    Yes, I wanted to stay Flash Player 9 compatible. I've heard FP10 Vectors give speedups with numbers, but not so much with objects.

    When I decompiled playerglobal.swc, I found there are 4 Vector classes that are actually implemented with AS3 code.

    dynamic final class Vector$int

    function Vector$int(length:uint=0, fixed:Boolean=false){
    super();
    this.length = length;
    this.fixed = fixed;
    }
    AS3 function shift():int{
    return (this._shift());
    }
    private function _shift(){
    if (this.fixed){
    Error.throwError(RangeError, 1126);
    };
    if (this.length == 0){
    return (undefined);
    };
    var _local1:* = this[0];
    this._spliceHelper(0, 0, 1, null, 0);
    return (_local1);
    }
    // etc.

    dynamic final class Vector$uint
    // similar code

    dynamic final class Vector$double
    // similar code

    dynamic final class Vector$object
    // similar code
    ...
    // this seems a bit ugly
    prototype.push = function (... _args){
    return (castToThisType(this).push.apply(castToThisType(this), _args));
    };
  • @robert ok, sure for bubbling you need the target. but my first impression was that the people where screaming for the target so the DeluxeSignal was born ;) but thats like two steps forward and one back. Sure if you like to have bubbling you need the target but then a BubblingSingnal would maybe better?
    Had you ever the situation where priority would be useful with the normal Signal?
  • @mich Also, the Signal constructor only accepts classes, so you can't pass a target to it, and there's no place to store it inside the Signal. So DeluxeSignal is necessary for that.
  • @mich Circling back to your question, target is required in DeluxeSignal because it is used to determine if the IEvent needs to be cloned, and also to bubble and set currentTarget.

    // clone re-dispatched event
    if (event.target)
    {
    valueObjects[0] = event = event.clone();
    }
    event.target = this.target;
    event.currentTarget = this.target;



    //// Bubble the event as far as possible.
    var currentTarget:Object = this.target;
    while ( currentTarget && currentTarget.hasOwnProperty("parent")
    && (currentTarget = currentTarget.parent) )
    {
    if (currentTarget is IBubbleEventHandler)
    {
    //TODO: incorporate secoif's Boolean return to check whether to continue.
    IBubbleEventHandler(event.currentTarget = currentTarget).onEventBubbled(event);
    break;
    }
    }
    }
  • I'd describe the Signal class as the most stable and heavily used in my and others' projects. DeluxeSignal is an experiment with implementing less-used features found in AS3 Events.
  • @mich DeluxeSignal has support for listener priorities and IEvent, and experimental support for bubbling. IEvent has APIs like target, currentTarget and clone(). DeluxeSignal has logic to automatically clone a re-dispatched IEvent and update its currentTarget property as it bubbles.
  • This is going to save me writing so much extra code. Creating your own events in AS3 always bugged me and this solution is very elegant. Very awesome, thanks!
  • @robert correct me if im wrong but as far as i interstand the DeluxeSignal is mainly for retrieving the target, no? when yes, why when you can pass the target/this within the dispatch method of the normal Signal? is it still needed?
  • Thanks John and Bob - removeAll() and addOnce() sound very nice.
  • As John said, there is signal.removeAll(), which EventDispatcher does not have.

    Also, Signal has addOnce(listener:Function), which will cause the listener to be automatically removed the first time it's called. This is perfect for load and complete events.
  • how much of a memory hit is leaving the listeners added for load events after they're finished loading?
  • John Lindquist
    @dehash - I assume you'll just add signal.removeAll() in any of your clean-up methods. That's something I need to look into a bit more myself too.

    @mich - onPunched/onKicked would work just fine. They're still just "listeners" like the current event system, so you can probably just follow your standard conventions.
  • very interesting these signals! indeed really really easy and simply. i was just wondering if there is a convention to name these? you used kicked, punched etc would it make sense to name them like onPunched onKicked to marked them as signals from the outside with on..?
  • Good and clear tutorial. Just wondering if you need to carefully clean up the signals up once you have finished using them like you do with Events using removeEventListener etc to avoid stuff getting stuck in memory.
blog comments powered by Disqus

Search

Recommended Books

Speaking at FITC Toronto

 

January 2010
M T W T F S S
« Dec    
 123
45678910
11121314151617
18192021222324
25262728293031

Preferred Video Tutorial Resolution

  • 1024x768 (53%, 85 Votes)
  • 1280x1024 (15%, 24 Votes)
  • 1920x1080 (15%, 24 Votes)
  • 800x600 (13%, 20 Votes)
  • 480x320 (4%, 6 Votes)
  • 640x480 (0%, 2 Votes)

Total Voters: 160

Loading ... Loading ...