[ 3 posts ]

Craig Phillips

  • Username: iwonbigbro
  • Joined: Tue Feb 01, 2011 3:50 am
  • Posts: 32
  • Location: United Kingdom
  • Offline
  • Profile

Events: Hazards of M.Do and EventTarget.on cocktails...

Post Posted: Fri Feb 03, 2012 7:10 am
+0-
Currently, the EventTarget.on method allows an event type, function and context, whereby the function must be a function reference. The problem with this model is that it inhibits any use of the M.Do functionality after something has been event bound in this way. A workaround to this is to bind events through M.bind, passing in the name of the function to bind to, though this does not scale as well as a simple function reference. Let me elaborate through example:

var eh = M.on("myEvent", this._onMyEvent, this);

Some time later, typically in a plugin or extension, you want to subscribe to the event handler itself as opposed to the event. This will ensure you can be handled before the handler you are subscribing too.

var eh = this.afterHostMethod("_onMyEvent", this._onMyEvent);

The afterHostMethod subscriber will not be called when _onMyEvent on the host is called through the event handler. The reason is that the injection of the M.Do method interface has happened after a reference to the original function was provided to the EventTarget.on method. In essence, the EventTarget class will call the original function via its reference instead of the new function on the host instance.

In hindsight, it may have been more sensible to either bind the event handler through M.bind("_onMyEvent", this) or to bind it as an after event, so that other events can subscribe to the actual event instead of the event handler method on the host. I wonder if there is yet another way to be able to ensure the ordering of event handlers on a particular broadcast event? What I need to guarantee is this:

[GlobalEvent]->[PluginHandler]->[HostHandler]

But with the HostHandler being an 'on' event handler, I see no way of achieving this without either changing it to 'after' or creating an M.Do handler on the host method. What's the best practice surrounding this type of scenario?

Luke Smith

YUI Contributor

  • Username: lsmith
  • Joined: Thu Aug 28, 2008 7:50 am
  • Posts: 507
  • Location: Sunnyvale
  • Twitter: ls_n
  • GitHub: lsmith
  • Gists: lsmith
  • IRC: ls_n
  • YUI Developer
  • Offline
  • Profile
Tags:

Re: Events: Hazards of M.Do and EventTarget.on cocktails...

Post Posted: Sat Feb 04, 2012 1:26 am
+0-
The added function hop for passing through bind is unlikely to show up on performance profiles unless the specific event occurs A LOT. I've personally changed to using string bind for all event subscriptions recently for exactly the reason you describe (See DataTable source on GitHub).

However, I also own the event system in YUI and plan to add support for late binding subscriptions into on() and the other subscription methods :)
http://yuilibrary.com/projects/yui3/ticket/2530233

In general, I would say that it sounds like it should have been bound as an after() subscription, since the AOP methods are intended to advise/alter existing logic. In the context of event handlers, doing *extra* work that stands apart from the work done in the other handler is best represented as a separate event handler.

That said, your concern is largely about ordering the handlers, which there is not much support for today. IME, this is often a sign that there's something in the architecture that could/should shift to make things fall into line with current APIs.

You should drop into #yui on freenode next week to chat about the use case more.

Craig Phillips

  • Username: iwonbigbro
  • Joined: Tue Feb 01, 2011 3:50 am
  • Posts: 32
  • Location: United Kingdom
  • Offline
  • Profile

Re: Events: Hazards of M.Do and EventTarget.on cocktails...

Post Posted: Mon Feb 06, 2012 5:15 am
+0-
Logged into freenode as cphillip.

It would definitely be nice to see support for later bindings in EventTarget. I was for a while using YUI.bind to bind functions to EventTargets, but in an effort to reduce the overhead of having the extra closure in memory and having to instantiate the closure during initialisation, both of which sap IE 7 and 8 of all ability to function normally under conditions created by the use case, I retracted the bind calls to pass in the function reference, thus leading me to discover the issue with early binding and YUI.Do. :-)

I am thinking of providing local versions of the events being subscribed to, so that plugins can modify their host behaviour without tampering with the host through YUI.Do. E.g.

// In the host...
Y.on("global-event", this._onGlobalEvent, this);

this.publish("local-event", {
eimitFacade: true,
defaultFn: this._onLocaleEvent
});

...

_onGlobalEvent: function(e) {
this.fire("local-event", { data: e.data });
},

_onLocalEvent: function(e) {
// Will happen after anything else that subscribes to this event and only
// if nothing prevents default (more control to subscribers).
},

// In the plugin...
this.get("host").on("local-event", function(e) {
// Happens before the default host handler.
});

this.get("host").after("local-event", function(e) {
// Happens after the default host handler?
});

Not sure about the integrity of the last handler, which is why made it a question instead of a statement. :-)
  [ 3 posts ]
Display posts from previous:  Sort by  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum