PDA

View Full Version : Anonymous Topic Style Pub/Sub system?



jonsykes
18 Aug 2011, 7:03 AM
Been poking around the code base, but I don't see anything obvious that fills this need.

Does 4.x not have an anonymous pub/sub system in place?

Something akin to dojo's publish/subscribe functionality

http://davidwalsh.name/dojo-pub-sub

LesJ
18 Aug 2011, 11:19 AM
You should be able to port to Ext this jQuery pub/sub plugin based on Dojo:

https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js

jonsykes
18 Aug 2011, 11:26 AM
Yeah, I'm actually doing that right now, hanging it off observable.

I was just surprised there was nothing baked in. There are 3 or 4 plugins and extensions that look great from 3 or 4 years ago, I just assumed one of those would have made it's way into the main codebase by now.

stevil
18 Aug 2011, 11:49 AM
It doesn't, but I whipped up a simple mechanism you could extend to your liking:



// Define


Ext.define('PubSub', {
extend: 'Ext.util.Observable',


statics: {
instance: null,


subscribe: function (topic, listener, scope) {
// Route messages through instance
if (!PubSub.instance) {
PubSub.instance = new this();
}


var inst = PubSub.instance;


// Ensure that event is declared
if (!inst.events[topic]) {
inst.addEvents(topic);
}


// Then listen on it, with declared scope
inst.mon(inst, topic, listener, scope || inst);
},


publish: function () {
var inst = PubSub.instance;
var args = Ext.Array.toArray(arguments);
var topic = args[0];


// If the topic has been declared through subscribe
if (inst && topic && inst.events[topic]) {
// A quirk in Observable requires me to lowercase the topic name
// I could have used inst.fireEvent(topic, args.slice(1))
// but the listener would get the args as a single array
// parameter in arguments[0].
// This allows the published arguments to be passed properly.

var evt = inst.events[topic.toLowerCase()];
evt.fire.apply(evt, args.slice(1));
}
}
}
});


// Subscribe


PubSub.subscribe('testTopic', function (a, b) {
alert(a + ' = ' + b);
}, this);


PubSub.subscribe('testTopic', function (a, b) {
alert(a + ' != ' + b);
}, this);


// Publish


PubSub.publish('testTopic', 'x', 5);


Note - this is rudimentary - it doesn't have topic management (remove listeners and event declarations), but that could be added.

hope this helps,

stevil

stevil
18 Aug 2011, 12:04 PM
Yeah, I'm actually doing that right now, hanging it off observable.

I was just surprised there was nothing baked in. There are 3 or 4 plugins and extensions that look great from 3 or 4 years ago, I just assumed one of those would have made it's way into the main codebase by now.

You're right - this is bread-and-butter functionality - I would think it would have made it in by now!

stevil

LesJ
18 Aug 2011, 2:33 PM
The Dojo code is self-contained, so you don't need to use the Ext's Observable.

Replace the jQuery plugin pattern by wrapping up the Dojo code in the Ext singleton.

Ext.define('Ext.PubSub', {
singleton: true,

// Copy the Dojo code here
});

I think that's all you need to do, but I didn't test it.

stevil
18 Aug 2011, 2:48 PM
The Dojo code is self-contained, so you don't need to use the Ext's Observable.

Replace the jQuery plugin pattern by wrapping up the Dojo code in the Ext singleton.

Ext.define('Ext.PubSub', {
singleton: true,

// Copy the Dojo code here
});

I think that's all you need to do, but I didn't test it.

True, and certainly simple, but so many things in the framework inherit Observable that it seems a natural pattern to follow.

stevil

jonsykes
22 Sep 2011, 4:51 AM
Just in case anyone is looking for copy paste example, this is what I am using, with some success.



/*
ExtJs pub/sub plugin by Jon Sykes (jon@sykes.me)

Loosely based on Dojo's Pub/Sub Topic handlers
Code lifted heavily from the jquery implementation by Peter Higgins
https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js

Original Discussion: http://www.sencha.com/forum/showthread.php?144261

*/
var cache= {};


Ext.define("Ext.topic", {
singleton: true,
// the topic/subscription hash
cache: {},


publish: function(/* String */topic, /* Array? */args){
// summary:
// Publish some data on a named topic.
// topic: String
// The channel to publish on
// args: Array?
// The data to publish. Each array item is converted into an ordered
// arguments on the subscribed functions.
//
// example:
// Add an event listener to a grid that publishes to the
// something/happened topic on select
//
// | listeners: {
// | 'select' : function(grid, rowIndex, e){
// | Ext.topic.publish("something/happened", [rowIndex]);
// | }
// | }
//
this.cache[topic] && Ext.each(this.cache[topic], function(){
this.apply(Ext.topic, args || []);
});
},


subscribe: function(/* String */topic, /* Function */callback){
// summary:
// Register a callback on a named topic.
// topic: String
// The channel to subscribe to
// callback: Function
// The handler event. Anytime something is $.publish'ed on a
// subscribed channel, the callback will be called with the
// published array as ordered arguments.
//
// example:
// Add an event listener to a panel that subscribes to the
// something/happened topic and triggers it's handler function
//
// example:
// | listeners:{
// | render: function(){
// | Ext.topic.subscribe("something/happened", this.handleChangeWell);
// | }
// | }
//
if(!this.cache[topic]){
this.cache[topic] = [];
}
this.cache[topic].push(callback);
return [topic, callback]; // Array
},


unsubscribe: function(/* Array */handle){
// summary:
// Disconnect a subscribed function for a topic.
// handle: Array
// The return value from a $.subscribe call.
// example:
// | var handle = Ext.topic.subscribe("something/happened", function(){});
// | Ext.topic.unsubscribe(handle);
// | // best practice would be to put these in an array and on destroy of
// | // the parent widget loop through and unsubsribe to all the topics.


var t = handle[0];
this.cache[t] && Ext.each(this.cache[t], function(idx){
if(this == handle[1]){
this.cache[t].splice(idx, 1);
}
});
}
});

jemptymethod
7 Aug 2012, 9:43 AM
You're right - this is bread-and-butter functionality - I would think it would have made it in by now!

stevil

We've all gotten our hands dirty with ExtJS4's "MVC" by now I presume. If so, we certainly understand why this sort of anonymous message pub/sub functionality is *not* baked in: it would not be in the spirit of the new "MVC" functionality. This is a shame because I got high praise for an ExtJS3 app I wrote using pubsub, but moving on to my next app using ExtJS4 I was required to use the MVC functionality and did not fare so well. Next time I'm thinking of using only the views, models, stores and application: no controllers. Views can easily get a handle on the app's viewport, and between the application, viewport, and anonymous message pub/sub style of development, I believe I will have everything necessary to succeed, *without* controllers: I'll let the application and/or viewport provide this sort of central control for the entire application.

wangyuelucky
17 Dec 2014, 12:21 AM
Can I use pub/sub pattern in the situation decoupling controllers? @jonsykes @jemptymethod