Listening for events on specific instances.

grapefrukt's Avatar

grapefrukt

26 Nov, 2009 01:50 PM

I regularly do my own collection classes to manage my Models. A collection is basically a thinly wrapped Vector. This holds a bunch of models and dispatch events as these are added, removed and sometimes selected. Nothing fancy going on there.

I've been slowly starting to use RobotLegs on smaller projects and it's been serving me fine, but my latest project featured two very similar collections, and this is where I ran into problems.

The two collections, both containing the same type of data, just two different sets, dispatch their events as they should, but due to what I assume is the common event bus (or whatchamacallit) the events fire on all listeners for both collections disregarding which one dispatched the event in the first place.

I could solve this by sending along the collection that was updated with the event and check that it's the one I want to listen for, but that seems very ugly. I could also do separate event classes and override the function that dispatches the events separately for each collection, but that also feels overly complicated.

What is the clever way to do this?

  1. Support Staff 1 Posted by Till Schneidere... on 26 Nov, 2009 02:02 PM

    Till Schneidereit's Avatar

    Depending on where you want to listen to these events, a third way
    might be to inject the collections and directly add listeners to them
    instead of the shared eventDispatcher.

  2. Support Staff 2 Posted by Shaun Smith on 26 Nov, 2009 04:33 PM

    Shaun Smith's Avatar

    Well, it depends on your design. You mention that you have "two very similar collections": are they managed by two instances of the same Model Actor? Might the list grow from 2 to N?

    If I need to manage two list that are similar, but represent two distinct parts of the application state, I would have two different Model classes - each would dispatch a different concrete Event. But that would only be suitable for certain designs.

    It would be good to get a little more info about what you are wanting to achieve.

  3. 3 Posted by grapefrukt on 26 Nov, 2009 06:59 PM

    grapefrukt's Avatar

    @tschneidereit: that also feels like sort of a hack, but it's definitively an option!

    @shaun: They are managed by two subclasses to a more generic collection class, but that's really just to avoid naming the injections and have more flexibility in changing the specific methods, it might as well just be two instances of the same class.

    In this specific instance I am making a greenscreen keying application (using air), so one collection is the "raw" images and the other is the already keyed ones. So, two distinct collections on which I need to do different things, but really the same type of data.

    And regarding list size; right now it's actually capped at twenty or so images per list just to keep things nice and fast. This might change depending on different requirements, but realistically never more than a couple of hundred.
    Worth noting is that I do not keep all the full images in memory, just thumbnails. I'm not crazy ;)

  4. Support Staff 4 Posted by Shaun Smith on 27 Nov, 2009 11:06 AM

    Shaun Smith's Avatar

    Aha! I wasn't so much interested in the number of items as the number of collections. It seems to me like you'd need two model actors:

    RawImagesModel and KeyedImagesModel

    Each model would manage access to it's underlying collection, and each would dispatch different events:

    RawImagesModelEvent and KeyedImagesModelEvent

    Even though the wrapped collection classes might be the same, the models represent two distinct areas of application state.

    As opposed to overriding the collections themselves (as you mentioned above) the models simply wrap the collections, expose an API to the system, and translate collection events (ImagesCollectionEvent.ITEM_ADDED) into system events (KeyedImagesModelEvent.ITEM_ADDED).

    Other parts of your system would then listen to the event bus for the appropriate concrete events. Be sure to use strong event typing when listening for these events if any of the string types overlap.

    Does that help at all?

  5. 5 Posted by grapefrukt on 27 Nov, 2009 01:40 PM

    grapefrukt's Avatar

    That is what I sort of expected I would have to do. I can see how it's clearly the most robust way, I was just a bit hesitant towards it because I felt I would be duplicating functionality.

    I'm just worried that it's a bit boilerplate'y to need different events just to be able to tell where they came from when they're more or less the same implementation wise.

    Would an option to listen for events dispatched by a specific instance be something that could be considered as an addition to the framework or do you think that will go too much against the overarching architecture?

  6. Support Staff 6 Posted by Shaun Smith on 07 Dec, 2009 02:43 PM

    Shaun Smith's Avatar

    Hi Grapefrukt,

    I'm having a little trouble understanding your last question (regarding an addition to the framework to listen for events dispatched by specific instances), could you expand on that?

  7. 7 Posted by redblind on 10 Dec, 2009 06:29 PM

    redblind's Avatar

    I believe grapefrukt is trying to determine which model is responsible for dispatching the event, so he can retrieve the data from that model. He is trying to avoid having two similar yet different events such as "KEYEDDATA_READY" and "RAWDATA_READY". He would prefer to just dispatch "DATA_READY" and be able to grab the data from the responsible model. He's thinking of having multiple instances of the event dispatcher.

    What I would do is have a third model being a collection of both keyed and raw data. When a model wants to make a data object available it will send that data to the third model. Whenever the third model receives new data it will dispatch an event of "DATA_READY." Whatever is listening to that third model can then go and retrieve the new data no matter if it's "raw" or "keyed". You can add a "type" property to your data object so you determine it's origin ("raw" or "keyed").

  8. 8 Posted by glidias on 14 Jan, 2010 05:03 PM

    glidias's Avatar

    Here's an idea though. Use namespace suffixing. Here's how you can go about it:

    Let's say IXMLAssetModel extends from a base interface/class called IAssetModel/AssetModel. IAssetModel can provide the following getter for easy reference:

    function get namespaceSuffix():String;

    For a Gaia asset node in the Gaia Flash Framework, for example, you could define a unique namespaceSuffix for each AssetModel (with a Gaia asset IAsset supplied to the AssetModel as a data dependency) from which a unique event string is dispatched by default from that model (ie. AssetEvent.SOME_EVENT_CONSTANT + namespaceSuffix).
    eg.
    <asset id="thumbnails" type="xmlRequestAsset" src="someURLThatReturnsXML.php" namespaceSuffix="gallery" model="com.blahblah.AssetModel">

    Then, you could manually map a framework event type of AssetEvent.ASSET_COMPLETE + thumbnailModel.namespaceSuffix to ensure a specific mediator only listen for notifications restricted to the "gallery" namespace within the framework, taking reference from the thumbnailModel's supplied namespaceSuffix value. Another way is to possibly read from the id of the AssetModel class and use that as the suffix. It all depends on your needs, whether the mediator just need to listen to a single asset, or to listen to a bunch of assets that belong to some particular namespace.

    Namespace suffixing for dispatched events might seem a bit messy, but it should work with minimal need to write duplicate code or unnecessary checks to filter off non-applicable mediators. Why hog performance by dispatching a site-wide event that only a few members within a specific context will respond to it? The solution, just add a namespace suffix to the event, so only the intended recipients will handle those.

  9. Stray closed this discussion on 11 Feb, 2011 11:26 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac