Skip to content

Instantly share code, notes, and snippets.

@addyosmani
Created October 28, 2011 06:49
Show Gist options
  • Select an option

  • Save addyosmani/1321768 to your computer and use it in GitHub Desktop.

Select an option

Save addyosmani/1321768 to your computer and use it in GitHub Desktop.
Four ways to do Pub/Sub with jQuery 1.7 and jQuery UI (in the future)

##Option 1: Using jQuery 1.7's $.Callbacks() feature:

var topics = {};
jQuery.Topic = function( id ) {
	var callbacks,
		method,
		topic = id && topics[ id ];
	if ( !topic ) {
		callbacks = jQuery.Callbacks();
		topic = {
			publish: callbacks.fire,
			subscribe: callbacks.add,
			unsubscribe: callbacks.remove
		};
		if ( id ) {
			topics[ id ] = topic;
		}
	}
	return topic;
};

Usage:

// Subscribers
$.Topic( 'mailArrived' ).subscribe( fn1 );
$.Topic( 'mailArrived' ).subscribe( fn2 );
$.Topic( 'mailSent' ).subscribe( fn1 );
// Publisher
$.Topic( 'mailArrived' ).publish( 'hello world!' );
$.Topic( 'mailSent' ).publish( 'woo! mail!' );
//  Here, 'hello world!' gets pushed to fn1 and fn2
//  when the 'mailArrived' notification is published
//  with 'woo! mail!' also being pushed to fn1 when
//  the 'mailSent' notification is published.
/*
output:
hello world!
fn2 says: hello world!
woo! mail!
*/

##Option 2: Using .on() and .off():

Ben Alman's really tiny pub/sub with my 1.7 updates from https://gist.github.com/1319216. The link to his gist with lots of useful comments is here: https://gist.github.com/661855

/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011
 * http://benalman.com/
 * Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */

(function($) {

  var o = $({});

  $.subscribe = function() {
    o.on.apply(o, arguments);
  };

  $.unsubscribe = function() {
    o.off.apply(o, arguments);
  };

  $.publish = function() {
    o.trigger.apply(o, arguments);
  };

}(jQuery));

Usage

// Super-basic example:

function handle(e, a, b, c) {
  // `e` is the event object, you probably don't care about it.
  console.log(a + b + c);
};

$.subscribe("/some/topic", handle);

$.publish("/some/topic", [ "a", "b", "c" ]);
// logs: abc

$.unsubscribe("/some/topic", handle); // Unsubscribe just this handler

// Or:

$.subscribe("/some/topic", function(e, a, b, c) {
  console.log(a + b + c);
});

$.publish("/some/topic", [ "a", "b", "c" ]);
// logs: abc
// Unsubscribe all handlers for this topic
$.unsubscribe("/some/topic"); 

##Option 3: Using the jQuery UI $.observables

Demo: http://jsfiddle.net/jUZmM/ Implem: http://view.jqueryui.com/grid/ui/jquery.ui.observable.js More information: http://wiki.jqueryui.com/w/page/47179578/Observable

/*$.observers/$.observables example by @addyosmani*/

The basic idea behind observables are that when objects/collections of data
are changed or updated, events often need to be triggered to inform any 
observers of the change. This is a concept you see in a few different 
frameworks (Backbone's Collections for example);

// The array I would like observed
var myData = [];

// An observer instance of my array, that can be observed
var observer = $.observer(myData); 

function dataChange( data ){
   console.log('New data arrived with ID ' + data[0].id + ' and value ' + data[0].title);   
}

// Bind a callback to be executed when the data
$(observer).bind("change", function ( e ) { 
    dataChange( e.target.data );
});

$.observable( myData ).insert({
                id: myData.length + 1,
                title: 'test'
            });
@connor
Copy link
Copy Markdown

connor commented Oct 28, 2011

this is awesome.

@gnarf
Copy link
Copy Markdown

gnarf commented Oct 28, 2011

It is pretty awesome, just want to put out a healthy reminder that $.observable is still evolving - $.observer is still a very new child, glad to see a demo of using it for something!

@ajpiano
Copy link
Copy Markdown

ajpiano commented Oct 28, 2011

Yeah, I am pretty sure that the observable stuff won't be available as part of jQuery UI 1.9

@addyosmani
Copy link
Copy Markdown
Author

Updating the gist to reflect correct version information on $.observable and $.observer being available.

@gnarf
Copy link
Copy Markdown

gnarf commented Oct 28, 2011

@addyosamani - $.observer was written very recently by @brado23 - I am pretty sure that it is in flux (but a useful helper for observables, right! :) )

I don't think of $.observer as a way to do pub/sub, that whole concept seems very rooted in a very simple string named "topic" structure. $.observer might help you with a keeping track of data in your storage arrays though, and give ways for other components to listen for change events on specific items or arrays.

@addyosmani
Copy link
Copy Markdown
Author

@gnarf37 that makes sense. Whilst pub/sub is slightly more event driven and $.observer is more data-oriented I consider them both as a part of the same family of observable patterns of development. I should probably come up with a better title for this gist :) Thanks for sharing the extra information about $.observer!. I'm finding out more and more about it as I read and play around with the code.

@pomeh
Copy link
Copy Markdown

pomeh commented Nov 6, 2011

this is nice :)

I would like to know what do you think about this problem. I've write a simple test case on jsFiddle if you want to see it in action and play with it.

Cheers

@furf
Copy link
Copy Markdown

furf commented Jan 11, 2012

Here's another variation where jQuery's event methods are "mixed in" to the supplied object or supplied function's prototype. Also includes a wildcard event for listening to all events. https://github.com/furf/jquery-enable/blob/master/src/bindable.js

@addyosmani
Copy link
Copy Markdown
Author

Niiiice @furf!

@eliperelman
Copy link
Copy Markdown

Hey @addyosmani, your first code snippet has an unused variable method. Just wanted to pass that along.

@addyosmani
Copy link
Copy Markdown
Author

Thanks for pointing that out @eliperelman! :) Fixed.

@eliperelman
Copy link
Copy Markdown

No problem, bud!

@mithun-daa
Copy link
Copy Markdown

Sweet Gist. Noob question. Why does Peter Higgin's pluggin start with a ; ??

@furf
Copy link
Copy Markdown

furf commented Feb 24, 2012

to ensure that in the event of js file concatenation, the javascript will not break if the previous file is missing a trailing semi-colon.

@mithun-daa
Copy link
Copy Markdown

@furf thank you sir. that makes total sense.

@crazy4groovy
Copy link
Copy Markdown

What about $.Deffered()? Can't those be used in some cases? https://tutsplus.com/lesson/deferreds/

@chaslewis
Copy link
Copy Markdown

Thanks! This is a really clear and practical overview of an important topic.
I'd make a slight modification to the first implementation to take topics out of the global space using the module pattern:

$.Topic = (function() {
    var topics = {};
    return function( id ) {
        // ... as above
        return topic;
    };
})();

@Salvodif
Copy link
Copy Markdown

Salvodif commented Feb 7, 2014

nice post

@prologic
Copy link
Copy Markdown

+1 gives me some ideas :)

@Janking
Copy link
Copy Markdown

Janking commented Jun 1, 2015

nice!

@murliatdure
Copy link
Copy Markdown

simple and effective

@gandhirahul
Copy link
Copy Markdown

Simply Amazing

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