js/pubsub.js
/**
* Pubsub for tracking events.
*
* Source: http://davidwalsh.name/pubsub-javascript
*/
export class PubSub {
constructor() {
this.topics = {};
}
/**
* Check if topic exists
* @param {String} topic The topic name
* @return {Boolean} True if the topic exists
*/
has(topic) {
return this.topics.hasOwnProperty(topic);
}
/**
* Subscribe to a given topic
* @param {String} topic The topic identifier to subscribe to
* @param {Function} listener The callback executed on topic publication
* @return {Object} A subscription handle with a single remove method.
*/
subscribe(topic, listener) {
// // Create the topic's object if not yet created
if (!this.has(topic)) {
this.topics[topic] = [];
}
// Add the listener to queue
var index = this.topics[topic].push(listener) -1;
// Provide handle back for removal of topic
return {
remove: () => {
delete this.topics[topic][index];
}
};
}
/**
* Unsubscribe to a given topic
* @param {String} topic The topic identifier to unsubscribe to
* @param {Function} listener The callback to unregister
*/
unsubscribe(topic, listener) {
if (!this.has(topic)) return;
this.topics[topic].some((handler, index) => {
if (handler === listener) {
delete this.topics[topic][index];
return true;
}
});
}
/**
* Subscribe once to a given topic
* @param {String} topic The topic identifier to subscribe to
* @param {Function} listener The callback executed on topic publication
*/
once(topic, listener) {
let subscription;
subscription = this.subscribe(topic, () => {
subscription.remove();
listener.apply(this, arguments);
});
}
/**
* Publish some data on a topic
* @param {String} topic The topic identifier
* @param {...[type]} args A vriable list of arguments to pass to the listeners
*/
publish(topic, ...args) {
// If the topic doesn't exist, or there's no listeners in queue, just leave
if(!this.has(topic)) return;
// Cycle through topics queue, fire!
this.topics[topic].forEach(function(handler) {
handler(...args);
});
}
/**
* Remove a topic (and all its listeners)
* @param {String} topic The topic identifier to remove
*/
remove(topic) {
if (this.has(topic)) {
delete this.topics[topic];
}
}
};
export var pubsub = new PubSub();
export default pubsub;