1

I'm trying to implement publish/subscribe pattern in Node but without Redis. The functionality should be the same; you can publish to a channel, subscribe to a channel and listen to data if you have subscribed; here are the Redis functions:

pub.publish('channel1', myData1, function (err, data) {     
});


sub.subscribe('channel1', function (err, data) {
});


sub.on("message", function (channel, data) {
    //Now you are easily listening to data
});

I have tried the following, which may not be a good way at all (I'm just showing my attempt!); I have my own channel object where I save the channels and functions which need to be triggered when we publish new data to a specific channel; so as you see I'm subscribing functions to channels; but, I don't know if there is any way I can listen to data like the way redis provids sub.on("message",function(){...! So could you please help me if I can do it the same way as the Redis does, but with eventEmitter or...

var events = require('events');
var emitter = new events.EventEmitter;
var channels = {};
//channels ={"channelA": ["func1", "func2"], "channelB": []}

//publish data to a channel and emits all of the functions which are registered for listening to the channel
function publish(channel, data, callback) {
    if (channels[channel] && channels[channel].length > 0) {
        for (var i = 0; i < channels[channel].length; i++) {
            emitter.emit(channels[channel][i], data);
        }
    }
    callback();

}

//subscribe a function to a channel
function subscribe(channel, FuncName, next) {
    if (!channels[channel]) {
        channels[channel] = [];
    }
    channels[channel].push(FuncName);
    next();
}

//Subscribe a callback function from a channel
function unsubscribe(channel, FuncName) {
    if (channels[channel]) {
        var indx = channels[channel].indexOf(FuncName);
        if (indx != -1) {
            channels[channel].splice(indx, 1);
        }
    }
}
user385729
  • 1,924
  • 9
  • 29
  • 42

1 Answers1

1

You could use an EventEmitter for each channel. Also, you probably want to save references to callbacks, not to function name strings.

var events = require('events');
var channels = {};

//publish data to a channel and emits all of the functions which are registered for listening to the channel
function publish(channel, data, callback) {
  if (channels[channel]) {
    channels[channel].emit('message', channel, data);
  }
  callback();
}

//subscribe a function to a channel
function subscribe(channel, fn, next) {
  if (!channels[channel]) {
    channels[channel] = new events.EventEmitter();
  }
  channels[channel].addListener('message', fn);
  next();
}

//unsubscribe a callback function from a channel
function unsubscribe(channel, fn) {
  if (channels[channel]) {
    channels[channel].removeListener('message', fn);
  }
}
Ben
  • 10,056
  • 5
  • 41
  • 42
  • Thanks so much man! I just dont understand `channels[channel].emit('message', channel, data);` why are you passing `channel` in this line? So for subscribe I need to pass a reference to my callback and when we publish to a channel which someone is subscribed to, we emit that callback function which is provided in subscribe, right? – user385729 Feb 06 '15 at 02:55
  • 1
    I included `channel` because your example included `channel` as one of the parameters to the callback (`sub.on("message", function (channel, data) {...})`). It is not really necessary. – Ben Feb 06 '15 at 18:43
  • `EventEmitter` keeps track of the callbacks for you. So, all you have to do is tell `EventEmitter` to call a callback when someone emits `message`. Another way to approach this would be to use a single `EventEmitter` and namespace the events. e.g. event names could be something like `channel + ':message'`. – Ben Feb 06 '15 at 18:46