Adding bidirectional to js pub/sub pattern

Pub/sub is a very effective javascript pattern in order to avoid direct access between code modules.
However its one-way mode may be frustrating as we often expect some reply that requires another reverse pub/sub.
Other JS patterns offers bidirectional, but require third-party libraries and heavyer code management.
We suggest improving a tiny javascript pub/sub implementation in order to provide bidirectional facilites.
How does pub/sub pattern work
Some module code 'publishes' a request, supplying topic name and data:
events.publish("users/info", id_user);
Any subscriber to that topic will handle this event:
events.subscribe("users/info", function(data){
	...			
});
Doing that, both emitting and receiving modules doesn't know anything about respective codes.
Vanilla JS pub/sub implementation
An events object including the subscribe and publish methods is defined inside the global space :
var events = (function(){
  var topics = {};
  var hOP = topics.hasOwnProperty;

  return {
    subscribe: function(topic, listener) {
      if(!hOP.call(topics, topic)) topics[topic] = [];

      var index = topics[topic].push(listener) -1;

      return {
        remove: function() {
          delete topics[topic][index];
        }
      };
    },
    publish: function(topic, info) {
      if(!hOP.call(topics, topic)) return;

      topics[topic].forEach(function(item) {
      		item(info != undefined ? info : {});
      });
    }
  };
})();
(A tiny implementation example coming from the David Walsh blog)
Doing more with less
If the publisher expects an answer, we need to implement another pub/sub where the subscriber will publish and the publisher will subscribe...
Hard coding such a process is not really "doing more with less" !

It would be nice, instead, to just provide some optional callback function to the publish request, in order to handle an incoming response from the subscriber:
events.publish("users/info", id_user, function(response){
	...
});
Bidirectional implementation
We can do this, adding a bit of code to the above pub/sub implementation example:
var events = (function(){
  var topics = {};
  var hOP = topics.hasOwnProperty;

  return {
    subscribe: function(topic, listener) {
      if(!hOP.call(topics, topic)) topics[topic] = [];

      var index = topics[topic].push(listener) -1;
	  
      return {
        remove: function() {
          delete topics[topic][index];
        }
      };
    },
    publish: function(topic, info, callback) {
      if(!hOP.call(topics, topic)) return;
 
      topics[topic].forEach(function(item) {
	      if(callback){
		      var UID = String(performance.now()) + Math.random().toString(36).substr(2, 10);
		      events.subscribe(UID, callback);
		      var c = function(d){events.publish(UID, d)}
		      item(info != undefined ? info : {},  c);
	      }else{
      		item(info != undefined ? info : {});
	      }
      });
    }
  };
})();
What did we do ?
Adding an optional callback function argument to the publish request:
publish: function(topic, info, callback) {
Handling it:
if(callback){
	var UID = String(performance.now()) + Math.random().toString(36).substr(2, 10);
	events.subscribe(UID, callback);
	var c = function(d){events.publish(UID, d)}
	item(info != undefined ? info : {},  c);
}
If a callback function is provided...
Before emitting its 'publish' request, the code creates an unique topic name (any other unique identifier code may do as well)...
var UID = String(performance.now()) + Math.random().toString(36).substr(2, 10);
...then creates a subscriber dedicated to handle some response using the provided callback function:
events.subscribe(UID, callback);
...then creates an other callback function which can be used by the initial subscriber to publish its response :
var c = function(d){events.publish(UID, d)}
item(info != undefined ? info : {},  c);
Bidirectional is effective now !
The publisher can add a callback function:
events.publish("users/info", id_user, function(response){
	// some code handling response...
});
The subscriber can reply:
events.subscribe("users/info", function(data, reply){
	//some code generating a response...
	reply(response);		
});
If no callback function is provided while publishing, the pub/sub works as usual...
Finally
This bidirectional improvement should be easily added to any other pub/sub implementation.

Every subscribe request including a callback function will generate a new topic name that will never be used again. You should improve the code to remove them after use...

Bidirectional pub/sub should be used with only one submitter, otherwise the publisher would get more than one response...