ruk·si

JS Pattern
Publisher

Updated at 2015-05-13 13:05
var Publisher = (function() {

  /**
   * @constructor
   */
  var Publisher = function() {
    this.topics = {};
    this.nextSubscriptionToken = 0; // could be UUID
  };

  /**
   * Broadcast content to subscribers of speficied topic.
   * @param {string} topic
   * @param {*} content
   * @returns {*}
   */
  Publisher.prototype.publish = function(topic, content) {
    if (!this.topics[topic]) {
      return false;
    }
    var subscribers = this.topics[topic];
    var count = subscribers ? subscribers.length : 0;
    for (var i = 0; i < count; i++) {
      subscribers[i].callback(topic, content);
    }
    return this;
  };

  /**
   * Subscribe to get publications on the specified topic.
   * @param {string} topic
   * @param {function:(string, object)} callback
   * @returns {string}
   */
  Publisher.prototype.subscribe = function(topic, callback) {
    if (!this.topics[topic]) {
      this.topics[topic] = [];
    }
    var token = this.nextSubscriptionToken.toString();
    ++this.nextSubscriptionToken;
    this.topics[topic].push({
      token: token,
      callback: callback
    });
    return token;
  };

  /**
   * Unsubscribe from receiving publications.
   * @param {string} token Subscription token returned by subscribe().
   * @returns {*}
   */
  Publisher.prototype.unsubscribe = function(token) {
    for (var topic in this.topics) {
      if (this.topics[topic]) {
        for (var i = 0, j = this.topics[topic].length; i < j; i++) {
          if (this.topics[topic][i].token === token) {
            this.topics[topic].splice(i, 1);
            return token;
          }
        }
      }
    }
    return this;
  };

  return Publisher;
}());

var mailPublisher = new Publisher();
mailPublisher.publish('inbox/newMessage', 'hello world!');

var loggerSubToken = mailPublisher.subscribe(
  'inbox/newMessage',
  function(topics, content) {
    console.log('Logging: ' + topics + ': ' + content);
  }
);
var moggerSubToken = mailPublisher.subscribe(
  'inbox/neverDo',
  function(topics, content) {
    console.log('Mogging: ' + topics + ': ' + content);
  }
);
mailPublisher.publish('inbox/removeMessage', 'hello world!');
mailPublisher.publish('inbox/newMessage', 'hello world!');
mailPublisher.publish('inbox/newMessage', ['test', 'a', 'b', 'c']);
mailPublisher.publish('inbox/newMessage', {
  sender: 'hello@google.com',
  body: 'Hey again!'
});
mailPublisher.unsubscribe(loggerSubToken);
mailPublisher.publish('inbox/newMessage', 'Hello! are you still there?');