Why use a callback function over triggering an event in jQuery? - javascript

I've seen the callback() concept used a lot in jQuery plugins and I'm starting to think triggering custom events could be a better alternative.
jQuery has a built-in mechanism to trigger('A_CUSTOM_EVENT') so why don't plugin authors simply trigger a 'COMPLETE_EVENT' rather than insist we pass in a callback function that is to handle this 'complete phase'.
Nick

This depends on what you are trying to achieve - it's an architectural choice.
Basically the event-paradigm is open, non-private and persistent. You have an public event, where everybody can register for, and their event functions are basically called as often as they wish until they unregister from the event. Makes sense for recurring events.
Example: Registering to a hover event.
The callback-paradigm is isolated, private and disposable. Someone calls your code and hands over a private callback, which will be disposed once it got executed. In most cases the usability is limited (limited to a single point in time) and/or should not necessarily be public.
Example: Handling an ajax response.
Both of these paradigms have advantages and drawbacks. Using one or the other is up to you and how you want your application to be used.

Related

In node.js, when to use events, when to use a straight callback function?

It seems to me that the "core" node.js callback syntax, i.e.
function foo(data, callback) {
callback(false, data2);
}
is semantically superseded by events, except that
With events, you lose the last bit of static checking
Events are more flexible
Once you have more than 2 or 3 callback-y functions, callbacks get rather clunky
Events might be a very slight perfomance overhead (but premature optimization would be an understatement in almost all cases)
(But then again, you have to memorize the events, too...)
So what would be a good policy for when to use what?
A good policy is to use whatever abstraction best models your use cases
I think performance is a non-issue in this case.
If you are providing a function to a client that performs an asynchronous call, exposing it as a single function (like your example) would seem to be completely valid, and seems to be pretty clean. (this seems to be the way most of the node.js db clients work).
Callbacks quickly get out of hand, when there are more than 2-3, as you mentioned. But would a 2-3 callback function be better modeled as an event emitter?? Maybe, and that's up to you.
IMO 2-3+ callbacks would definately be better modeled using promises, as the calling structure would be flatter.
IMO Event Emitters are often used in longer standing objects. Objects that are alive for a "longer" duration. Where you would like to create an object and subscribe to events over some period of time, which seems to be a completely different use case than a single async function that exposes a callback.
Another option is to model your client as a stream.
I think a good rule of thumb is to see where node standard library (and popular node libararies) applies event emitter to clients, vs where it provides a callback based api to clients.
Node models its tcp client/server as an event emitter

Emit/Subscribe pattern vs. Pipe in Famous

Both methods can be used so that one event handler can listen to the firing of an event from another event handler. The documentation says they are the same thing, just different implementation. I'm wondering why the framework bothers providing two different methods for this same task? Probably pipe() is better for chaining, but I'm wondering if there is any other hidden advantage of using pipe() over emit()/subscribe()
If you do widgetA.pipe(widgetB) then all events from widgetA are sent to widgetB regardless whether widgetB is listening to them. Pipe is like a firehose.
Subscribe on the other hand, is more performant. WidgetB.subscribe(widgetA) says "of the things you emit, I want to subscribe to a particular subset." Other events are then completely ignored.
This is especially important when interacting with the DOM, which outputs a lot of events (mousedown, mouseup, touchmove, resize, etc...), and it's preferred to use Subscribe when listening to a DOM element.

Unsubscribing from a published event with JavaScript

I have a website that users can dynamically add widgets to. These widgets use the Peter Higgins pub/sub plug-in to $.(subscribe) to an event that I $.(publish) from another 'core' module.
I have widgets in their own name space like this:
km.widget.name1,
km.widget.name2,
etc.
So the handles created by $.(subscribe) aren't global.
I do not know how to unsubscribe these widgets when the user decides to remove the widget from their custom page.
Also, how would I know which widget to unsubscribe from?
This doesn't solve your problem directly, but it may very well help you out. This is a recent blog by Sam Clearman. He describes a way to handle publish/subscribe events without using that plugin:
jQuery custom events provide a built in means to use the publish subscribe pattern in a way that is functionally equivalent, and syntactically very similar, to Higgin’s pub/sub plugin: Just bind observers to document.
Doing it this way, you may be able to solve your current issues.
I haven't used the pubsub plugin before, but I just glanced at the source code and it looks like you can unsubscribe in exactly the same as as you subscribe, just using $.unsubscribe(...) rather than $.subscribe(...).
Is this something you already know, and the problem is caused by your widget namespacing? I'm not really sure of what you mean by namespacing, anyway, since JavaScript doesn't support true namespaces (just objects - which I'm guessing is what you're using).

Controlling the order that event handlers / listeners are executed in

Once again the IE Monster has hit me with an odd problem.
I'm writing some changes into an asp.net site I inherited a while back. One of the problems is that in some pages there are several controls that add Javascript functions as handlers to the onload event (using YUI if that matters). Some of those event handlers assume certain other functions have been executed.
This is well and good in Firefox and IE7 as the handlers seem to execute in order of registration. IE8 on the other hand does this backwards.
I could go with some kind of double-checking approach but given the controls are present in several pages I feel that'd create even more dependencies. So I've started cooking up my own queue class that I push the functions to and can control their execution order. Then I'll register an onload handler that instructs the queue to execute in my preferred order.
I'm part way through that and have started wondering 2 things:
Am I going OTT?
Am I reinventing the wheel?
Anyone have any insights? Any clean solutions that allow me to easily enforce execution order?
I could not find any Standard that would define the call-order of events. This is not an issue this is pure anarchy :D
Also there's hundreds of independent implementations of this pattern, so it is unlikely that they would behave coherently anytime soon.
So yes you're off on your own.
The cleanest and most compatible approach I have, involves registering just one event-handler :D That way the native order becomes irrelevant.
Now the trick is to add your own predictable event-management on top of that - using a library, extending with nodeJS's version for example, depending on your requirements.
Note that JS gives you the freedom to just override the prototype-derived functions, so another possibility is something like this:
function eventify(element){
element._event = {}
element.on = element.addListener = function(evt,fn){ ... }
element.off = element.removeListener = function(evt,fn){ ... }
element.emit function(evt,args...){ ... do it the right way ... }
}
So maybe you are a little off track in considering queues and locking-mechanisms :)

Unobtrusive Javascript Obfuscates Event Handling

You know what I liked best about obtrusive javascript? You always knew what it was going to do when you triggered an event.
<a onclick="thisHappens()" />
Now that everybody's drinking the unobtrusive kool-aid it's not so obvious. Calls to bind events can happen on any line of any number of javascript file that get included on your page. This might not be a problem if you're the only developer, or if your team has some kind of convention for binding eventhandlers like always using a certain format of CSS class. In the real world though, it makes it hard to understand your code.
DOM browsers like Firebug seem like they could help, but it's still time consuming to browse all of an element's event handler properties just to find one that executes the code you're looking for. Even then it usually just tells you it's an anonymous function() with no line number.
The technique I've found for discovering what JS code gets executed when events are triggered is to use Safari's Profiling tool which can tell you what JS gets executed in a certain period of time, but that can sometimes be a lot of JS to hunt through.
There's got to be a faster way to find out what's happening when I click an element. Can someone please enlighten me?
Check out Visual Event... it's a bookmarklet you can use to expose events on a page.
If you're using jQuery you can take advantage of its advanced event system and inspect the function bodies of event handlers attached:
$('body').click(function(){ alert('test' )})
var foo = $('body').data('events');
// you can query $.data( object, 'events' ) and get an object back, then see what events are attached to it.
$.each( foo.click, function(i,o) {
alert(i) // guid of the event
alert(o) // the function definition of the event handler
});
Or you could implement your own event system.
To answer your question, try using the Firebug command line. This will let you use JavaScript to quickly grab an element by an ID, and then iterate through its listeners. Often, if used with console.log, you'll even be able to get the function definitions.
Now, to defend the unobtrusive:
The benefit I find in unobtrusive JavaScript is that it is a lot easier for me to see the DOM for what it is. That said, I feel that it is generally bad practice to create anonymous functions (with only few exceptions). (The biggest fault I find with JQuery is actually in their documentation. Anonymous functions can exist in a nether-world where failure does not lead to useful output, yet JQuery has made them standard.) I generally have the policy of only using anonymous functions if I need to use something like bindAsListener from Prototype.
Further, if the JS files are properly divided, they will only be addressing one sub-set of the DOM at a time. I have an "ordered checkbox" library, it is in only one JS file which then gets re-used in other projects. I'll also generally have all of the methods of a given sub-library as member methods of either a JSON object or a class and I have one object/class per js file (just as if I were doing everything in a more formalized language). If I have a question about my "form validation code", I will look at the formValidation object in formvalidation.js.
At the same time, I'll agree that sometimes things can become obtuse this way, especially when dealing with others. But disorganized code is disorganized code, and it is impossible to avoid unless you are working by yourself and are a good programmer.
In the end, though, I would rather deal with using /* */ to comment out most of two or three js files to find misbehaving code, then go through the HTML and remove the onclick attributes.
Calling it "kool-aid" seems unfair. DOM Level 2 events solve specific problems with inline event handling, like the conflicts that always result. I don't look back to writing code to use window.onload that has to check whether someone else has assigned it before, and sometimes having it overriden by accident or out of sloppiness. It also ensures a better separation of the structure (HTML) and behaviour (JS) layers. All in all, it's a good thing.
Regarding debugging, I don't think there's any way to solve the event handlers being anonymous functions, other than nagging the authors to use named functions where possible. If you can, tell them that it produces more meaningful call stacks and makes the code more maintainable.
One thing: you shouldn't be able to see what will happen in JavaScript by looking at the HTML code. What nuisance is that? HTML is for structure.
If you want to check what events are bound to certain elements, there's a bookmarklet called visual event for now, and firebug 1.6 (IIRC) will have some sort of event inspector.

Categories