Thursday, January 21, 2010

AS3 Signals Tutorial

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:



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 1024x768 from here on out.

73 comments:

  1. 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.

    ReplyDelete
  2. 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..?

    ReplyDelete
  3. John Lindquist6:40 AM

    @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.

    ReplyDelete
  4. 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.

    ReplyDelete
  5. Thanks John and Bob - removeAll() and addOnce() sound very nice.

    ReplyDelete
  6. @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?

    ReplyDelete
  7. 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!

    ReplyDelete
  8. @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.

    ReplyDelete
  9. 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.

    ReplyDelete
  10. @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;
    }
    }
    }

    ReplyDelete
  11. @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.

    ReplyDelete
  12. @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?

    ReplyDelete
  13. [...] out. Until yesterday I had only briefly looked at the project but after John Lindquist’s video tutorial I’m completely sold on the idea and look forward to using it in my [...]

    ReplyDelete
  14. 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! :)

    ReplyDelete
  15. thanks for the tutorial John.
    you got me hooked to AS3 signals

    ReplyDelete
  16. [...] new every day. I’ve stumbled upon a great API by Robert Penner called AS3 Signals. Watch this video on pv3d.org to get [...]

    ReplyDelete
  17. Karl Knocking3:37 AM

    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?!

    ReplyDelete
  18. 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

    ReplyDelete
  19. John Lindquist4:36 AM

    I believe the third parameter is optional, so you can just write NativeSignal(this, MouseEvent.CLICK);

    ReplyDelete
  20. P48l04:54 AM

    this stuff sounds interesting, i will read more about this.

    ReplyDelete
  21. @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));
    };

    ReplyDelete
  22. Hi, just to let you know if you click on the image it loads the wrong tutorial - installing Haxe tutorial.
    Thanks

    ReplyDelete
  23. johnlindquist4:27 AM

    Thanks, fixed it.

    ReplyDelete
  24. [...] community about a new library by Robert Penner called as3-signals. John Lindquist recently posted a video tutorial on using it, and I thought I’d follow up with a nice text-based tutorial explaining the [...]

    ReplyDelete
  25. misha726:07 AM

    @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....


    Lets say we call it MemorySignal.

    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.

    ReplyDelete
  26. [...] Lindquist has a “must watch” video tutorial that will sell the idea and simplicity of AS3Signals to just about any flash [...]

    ReplyDelete
  27. [...] good resources of getting started with AS3 Signals is this video by John Lindquist. I don’t know about you, but I have found that these screencasts are a [...]

    ReplyDelete
  28. Scott6:07 AM

    Thanks for the great tutorial!

    ReplyDelete
  29. Nicole Chung12:31 AM

    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?

    ReplyDelete
  30. 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.

    ReplyDelete
  31. ocorso3:35 PM

    how much of a memory hit is leaving the listeners added for load events after they're finished loading?

    ReplyDelete
  32. misha722:33 AM

    yes, I will do it.

    ReplyDelete
  33. Native Signals have to dispatch Events.

    ReplyDelete
  34. [...] Signals as replacement for events. Signals can do much more cool stuff so make sure you watch this video tutorial and you can get started with Signals right away. Download Signals swc [...]

    ReplyDelete
  35. Jason Merrill4:49 AM

    Does this event API support event bubbling at all? I couldn't tell from the video.

    ReplyDelete
  36. I have reviewed your Web site and has very good resources like this one. Thanks to put at the disposal of all these subjects

    ReplyDelete
  37. [...] http://pv3d.org/2010/01/21/as3-signals-tutorial/ [...]

    ReplyDelete
  38. [...] Penner (http://github.com/robertpenner/as3-signals) – I followed a tutorial at this link http://pv3d.org/2010/01/21/as3-signals-tutorial/. This is a fairly significant change to the internal communication of the game, it will help with [...]

    ReplyDelete
  39. [...] Penner (http://github.com/robertpenner/as3-signals) – I followed a tutorial at this link http://pv3d.org/2010/01/21/as3-signals-tutorial/. This is a fairly significant change to the internal communication of the game, it will help with [...]

    ReplyDelete
  40. jimmidahand1:33 PM

    What are u editing in.

    ReplyDelete
  41. hidrodixtion3:49 PM

    Hai Robert . Thanks so much for this tutorial, I really really like signal and will implement it ASAP =)

    ReplyDelete
  42. [...] see but I ended up on this one because of the presenter. I had seen John Lindquist (@johnlindquist) code, now I wanted to see him speak. His presentation was about 3D on the web; where it started and [...]

    ReplyDelete
  43. bindiry3:24 AM

    What does the font used in FDT?

    ReplyDelete
  44. Nikos5:49 AM

    How to you survive without the datacentric features of flash builder 4and use FDT?
    although I love the code gen stuff your video shows?

    ReplyDelete
  45. Very Nice thanks for that.

    ReplyDelete
  46. [...] tutorial for those interested, doubtful though as I don’t think I could any better then this John Lindquist Signals Tutorial. Check it out! Signals vs Events [...]

    ReplyDelete
  47. [...] mejor tutorial que pude encontrar fue el siguiente video, (obtenido del wiky del proyecto en github) que explica de una manera clara las capacidades de este [...]

    ReplyDelete
  48. Francois Massart3:33 AM

    Could you share your tips and tricks about FDT in a new post, that would be nice.
    I think about hot keys, shortcuts, templates and maybe settings/preferences.
    It is very impressive :) Thanx

    ReplyDelete
  49. [...] event handling framework from Robert Penner that’s gaining popularity lately. There’s a good video tutorial by John Lindquist and tutorials [...]

    ReplyDelete
  50. johnlindquist9:40 AM

    In general, it's best to avoid Static util classes (there's a few Event-based ones like the one you referenced) so that your apps won't clash if they live side-by-side and share the same event types. It's the same reason why the Robotlegs eventDispatcher is injected into each class rather than being a Static util.

    ReplyDelete
  51. How would they clash, even if they shared event types? This approach will only hear events dispatched directly to the attached EventDispatcher instance...

    ReplyDelete
  52. Danielmacias1312:39 PM

    If you're interested in code-gen stuff similar to FDT for FlashBuilder, try SourceMate. At the time it's $80. There's a 30 trial, I just started using it.

    ReplyDelete
  53. [...] John Lindquist published a great rapid-fire 17-min. demo of using AS3 Signals. He presents examples of using 3 types of Signals: [...]

    ReplyDelete
  54. Richard Tazwoszky1:29 PM

    Is there a way in flashbuilder 4 to make it pop up that suggest box and then have it create the variable for you and import the class for you?

    Would appreciate it.

    ReplyDelete
  55. Chichilatte5:50 AM

    john, you are *great* at showing, thank you!

    ReplyDelete
  56. [...] This article by Ruben is a nice, jargon-free explanation of the AS3 event model, which applies to other languages in concept if not in syntax. It’s worth getting a handle on this powerful tool and also to keep in mind that it is not the only way to send signals between loosely couple objects in a software project. In fact the Signals and Slots methods use in other platforms such as Qt are very useful extensions of the event model. John Lindquist has a video tutorial using the AS3-Signals library for AS3 here [...]

    ReplyDelete
  57. As3 is a good one i believe just know watched videos through you tube, thanks for sharing nice one, keep sharing and updating. At the time it's $80. There's a 30 trial, I just started using it.

    ReplyDelete
  58. Download a free AS3-Signals Presentation PDF and AS3-Only project here!

    http://www.blog.rivellomultimediaconsulting.com/posts/as3-signals-introduction-presentation

    -Samuel Asher Rivello
    http://www.RivelloMultimediaConsulting.com

    ReplyDelete
  59. [...] No words can explain it better than a good screencast: http://johnlindquist.com/2010/01/21/as3-signals-tutorial/ [...]

    ReplyDelete
  60. Thanks for the clear intro. Time to go in deep now :-)

    ReplyDelete
  61. This As3 tutorial is really good and thanks for sharing this great information.

    ReplyDelete
  62. Thomas Thorstensson2:07 PM

    in latest Flashbuilder, when writing a function or untyped var in your class try pressing CTRL + 1 :

    it can create var for you either as local or field, and even entire method! Ohhh.

    ReplyDelete
  63. Thomas Thorstensson8:49 AM

    What is wrong with this if in the init class (as in main application class):

    if (stage){
    init();
    }else{
    added = new NativeSignal(this,Event.ADDED_TO_STAGE,Event);
    added.add(init);
    }

    It throws an error with this = null . Is there a way around this for ADDED_TO_STAGE or am I missing something obvious

    ReplyDelete
  64. Thomas Thorstensson9:59 AM

    Oh dear ignore this post notice then ";"

    Oh dear oh dear. Spank, self spank. Self spank.

    ReplyDelete
  65. Really cool tutorial, Is there a way in flashbuilder 4 to make it pop up that suggest box ?

    ReplyDelete
  66. Thanks alot for sharing this john, amazing tutorial

    ReplyDelete
  67. Nice blog and good video tutorial , thanks for sharing.

    ReplyDelete
  68. [...] some subcontracting work on an existing project that uses AS Signals. I checked out John Lindquist’s video tutorial on the subject. It’s a very good intro. Signals looks fairly easy to use. There’s a bit to understand [...]

    ReplyDelete