UNPKG

publisher-subscriber-ts

Version:
189 lines (184 loc) 6.68 kB
import { v4 } from 'uuid'; /** * @author Harsh A. Mistry * * Subscriber class to start listening to any topic */ var Subscriber = /** @class */ (function () { function Subscriber(callBack, topicName) { this._callBack = callBack; this._id = v4(); this._topicName = topicName; } Object.defineProperty(Subscriber.prototype, "callBack", { /** * Getter for callback * * @returns {Function} callback function provided while subscribing */ get: function () { return this._callBack; }, enumerable: false, configurable: true }); Object.defineProperty(Subscriber.prototype, "id", { /** * Getter for subscrber ID. Used for unsubscription. * * @returns {string} subscription ID */ get: function () { return this._id; }, enumerable: false, configurable: true }); Object.defineProperty(Subscriber.prototype, "topicName", { /** * Getter for topic name. Used for unsubscription. * * @returns {string} topic name */ get: function () { return this._topicName; }, enumerable: false, configurable: true }); return Subscriber; }()); /** * @author Harsh A. Mistry * * Topic class for creating new topic. Topic is a medium for communicating between publisher and subscriber. A publisher will create topic and subscriber will * subscribe to topic/topics */ var Topic = /** @class */ (function () { function Topic(topicName) { this._topicName = topicName; this._subscriberList = new Array(); } /** * Publish any event for current topic. Once event is published all active subscribers will get a notification in callback function. * @param {any} event */ Topic.prototype.publish = function (event) { this._currentValue = event; for (var _i = 0, _a = this._subscriberList; _i < _a.length; _i++) { var subscriber = _a[_i]; this.emitValueToSubscriber(subscriber); } }; /** * Once topic is created, it can be subscribed using this method * @param {Function} callback * @param {SubscribeOption} option Different option can be passed while subscribing. * e.g. If topic has already emitted some value and then a subscriber comes, then it can pass option to re-emit last emitted value only for this new subscriber. * * @returns {Subscriber} Final subscriber object once successfully subscribed */ Topic.prototype.subscribe = function (callback, option) { var subscriber = new Subscriber(callback, this._topicName); if (option.getLastValue && this._currentValue) { this.emitValueToSubscriber(subscriber); } this._subscriberList.push(subscriber); return subscriber; }; /** * Method to unsubscribe/remove a listener of this topic * @param {Subscriber} subscription Subscriber of this topic */ Topic.prototype.unsubscribe = function (subscription) { if (subscription && subscription.id) { var removeAtIndex = this._subscriberList.findIndex(function (subscriber) { return subscriber.id === subscription.id; }); if (removeAtIndex > -1) { this._subscriberList.splice(removeAtIndex, 1); } } }; Object.defineProperty(Topic.prototype, "topicName", { /** * Returns topic name * * @returns {string} */ get: function () { return this._topicName; }, enumerable: false, configurable: true }); /** * Broadcast value to given subscriber * @param {Subscriber} subscriber */ Topic.prototype.emitValueToSubscriber = function (subscriber) { if (this._currentValue) { subscriber.callBack.call(this, this._currentValue); } }; return Topic; }()); /** * @author Harsh A. Mistry * * Publisher class to publish new topics and emit values */ var Publisher = /** @class */ (function () { function Publisher() { } /** * Creates new topic for given topic name * @param {string} topicName Name for topic to be created * * @returns {Topic} New created topic */ Publisher.createTopic = function (topicName) { var topic = new Topic(topicName); this._topicMap.set(topicName, topic); return topic; }; /** * Subscribe to a particular topic by providing option and a callback function. * @param {SubscribeOption} option * @param {Function} callback * @throws {Topic name cannot be empty or null while subscribing} Error if topic name passed is null or empty * @throws {'Cannot find topic with name: ' ${topic_name} '. Please create one and then subscribe.'} If given topic name does not exist * * @returns {Subscriber} */ Publisher.subscribeTopic = function (option, callback) { var _a, _b; if (!option.topicName) { throw new Error('Topic name cannot be empty or null while subscribing'); } else if (!this._topicMap.has(option.topicName)) { throw new Error('Cannot find topic with name: ' + option.topicName + '. Please create one and then subscribe.'); } else if (this._topicMap) { return (_b = (_a = this._topicMap) === null || _a === void 0 ? void 0 : _a.get(option.topicName)) === null || _b === void 0 ? void 0 : _b.subscribe(callback, option); } }; /** * Unsubscribe any topic for given subscriber * @param {string} topicName * @throws {'Cannot find topic with name: ' ${topicName}} Thrown when given topic name is not found * @param {Subscriber} subscriber Subscriber of this topic */ Publisher.unsubscribeTopic = function (subscriber) { var _a, _b; if (!this._topicMap.has(subscriber.topicName)) { throw new Error('Cannot find topic with name: ' + subscriber.topicName); } else { (_b = (_a = this._topicMap) === null || _a === void 0 ? void 0 : _a.get(subscriber.topicName)) === null || _b === void 0 ? void 0 : _b.unsubscribe(subscriber); } }; Publisher._topicMap = new Map(); return Publisher; }()); export { Publisher };