Skip to content

Instantly share code, notes, and snippets.

@boazsender
Created May 8, 2011 02:55
Show Gist options
  • Select an option

  • Save boazsender/961057 to your computer and use it in GitHub Desktop.

Select an option

Save boazsender/961057 to your computer and use it in GitHub Desktop.
Implementing what a static jQuery pubsub might look like even though everyone hates the idea.
/*
usage:
$.bind('customEvt', function( event ){
console.log( event );
});
$.trigger('customEvt');
*/
;(function ($) {
$.bind = function( type, data, fn ){
if ( arguments.length === 2 || data === false ) {
fn = data;
data = undefined;
}
jQuery.event.add( document, type, fn, data );
};
$.trigger = jQuery.event.trigger;
})( jQuery );
@boazsender

Copy link
Copy Markdown
Author

I think $.bind and $.trigger are the jQuery way to do pubsub, and these methods should be provided by the library.

$(document).bind seems weird and wasteful to me. In this plugin, I skip the step of the selector check on document, and pass document directly into jQuery.event.add by default. While this is only a very small performance increase, I think it makes a lot more sense as an API.

It might also make sense to add an overload to jQuery.event.add to cater to off dom events.

If we take this seriously, it could lead to even more performance increases in off DOM events, and given a supported API, we could see users start organizing their larger jQuery Apps using $.bind and $.trigger.

@rwaldron

rwaldron commented May 8, 2011

Copy link
Copy Markdown

Attaching that static .bind() method will clobber the native .bind() ( Function.prototype.bind )

@rwaldron

rwaldron commented May 8, 2011

Copy link
Copy Markdown

jQuery.trigger = jQuery.event.trigger;

No need to wrap it in another function

@boazsender

Copy link
Copy Markdown
Author

That's a good point. $.subscribe?

@rwaldron

rwaldron commented May 8, 2011

Copy link
Copy Markdown

Also, need an "un" method

@rwaldron

rwaldron commented May 8, 2011

Copy link
Copy Markdown

$.subscribe brings us right back to the beginning :/\

@rwaldron

rwaldron commented May 8, 2011

Copy link
Copy Markdown

Performance wise, there is no statistical significance: http://jsperf.com/fn-bind-vs-bind

Also, run that page, then open the console and paste this: jQuery(document).data()[jQuery.expando] inspect the events property and you'll see that both events were add to the document object

@boazsender

Copy link
Copy Markdown
Author

Static bind is 15% faster.

Also, they both make use of the same document. All my plugin does is bypass the overload look up at the beginning of jQuery.fn.init. With further modification and tuning, jQuery.event could make off DOM events even more performant by not requiring a document to work.

@boazsender

Copy link
Copy Markdown
Author

Regarding jQuery.trigger = jQuery.event.trigger;

This wouldn't work because jQuery.event.trigger expects a jQuery collection.

@rwaldron

rwaldron commented May 8, 2011

Copy link
Copy Markdown

jQuery.event.trigger doesn't expect a jQuery collection, it's a static method. http://jsfiddle.net/rwaldron/Z56dG/1/ proves that my suggestion works exactly as expected.

I'm not sure where you get 15% faster from - it's incorrect. Of the 2 of 3 recorded results on that jsperf show $doc.bind being faster, but not even enough to be considered statistically significant. http://en.wikipedia.org/wiki/Statistical_significance

@boazsender

Copy link
Copy Markdown
Author

Whoops, I was looking at jQuery.fn.trigger (https://github.com/jquery/jquery/blob/master/src/event.js#L971), and not jQuery.event.trigger. Good point.

@boazsender

Copy link
Copy Markdown
Author

Also, when you perform an entire publish/subscribe, static bind trigger is 46 percent faster: http://jsperf.com/bind-vs-fn-bind

@boazsender

Copy link
Copy Markdown
Author

When you run your jsperf, it comes out 12 - 15% faster every time.

Also, when you perform an entire publish/subscribe, static bind/trigger is 46% faster than the dynamic methods: http://jsperf.com/bind-vs-fn-bind

@rwaldron

rwaldron commented May 8, 2011

Copy link
Copy Markdown

With all due respect, that jsperf doesn't tell me anything about trigger. there is way too much going on in those tests to really gauge anything. Take a look at this: http://jsperf.com/trigger-vs-fn-trigger Again, the differences are statistically insignificant. This has proven to be a great academic exercise

@rwaldron

rwaldron commented May 8, 2011

Copy link
Copy Markdown

Neither of you jsperfs are testing anything conclusive. Please review these...

http://jsperf.com/fn-bind-vs-bind

http://jsperf.com/trigger-vs-fn-trigger

@rwaldron

rwaldron commented May 8, 2011

Copy link
Copy Markdown

I think the confusion is that you're looking at the individual test results and not the stored results at the bottom (in the browserscope table)

@boazsender

Copy link
Copy Markdown
Author

I updated the $.trigger to directly reference jQuery.event.trigger.

@rmurphey

rmurphey commented May 9, 2011

Copy link
Copy Markdown

What's the benefit of going through the jQuery event system vs just maintaining an independent, pubsub-only object that tracks subscriptions, a la the @phiggins approach?

@boazsender

Copy link
Copy Markdown
Author

rmurphy: I agree, we should be using an of DOM event pubsub object for managing subscriptions. My thinking is that in the event.js rewrite an overload would be provided in jQuery.event.add() that allows for not passing a DOM element, in which case events would get added to a pubsub-only object.

I realize that jQuery is a DOM-centric library, but a lot of people use jQuery which gives it the power to teach people good practices, and providing a documented jQuery style way of doing pubsub could lead users to do off DOM events well.

Imagine using the jQuery event like so

$.bind('customEvt', function( e ){
console.log( e.data ); // my message
console.log( e.type ); // customEvt
});

$.trigger('customEvt', 'my message');

e.data and e.type are familiar to jQuery users. I feel like extending this familiar API to pubsub would be enormously influential, and if it's only ~10 lines of code, it might be worth it.

I also have some ideas about jQuery managing event bubbling off DOM which I'm still thinking through.

@rwaldron

Copy link
Copy Markdown

Re: $.bind... please re-read above.

@boazsender

Copy link
Copy Markdown
Author

I realize that $.bind and e.data clobber native properties (of function and message event respectively) which is probably bad, but that's another story. If it becomes clear that a built in pub sub is a good idea, then we can work out the semantics later. $.on, or something (which is not very jQuery :( ).

@rwaldron

Copy link
Copy Markdown

$.bind === Function.prototype.bind; // true get it? its not "just a property" its a fundamental jQuery-will-not-do-it deal breaker.

Additionally, your most recent example is not handling custom data correctly, See: http://jsfiddle.net/rwaldron/jEU3w/

"not very jQuery"? What then, would be "jQuery" enough for you?

As for "overloads", the whole point of the 1.7 events re-write is to stop doing major overloads and create straight forward behaviours that are both backwards compatible and future proof.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment