Skip to content

Commit

Permalink
Update hasSubscribers method to check if there is at least one subscr…
Browse files Browse the repository at this point in the history
…iber if no argument passed.
  • Loading branch information
georapbox committed Jan 23, 2017
1 parent fb52511 commit 76a09b7
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 46 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# CHANGELOG

## v3.1.0
- `hasSubscribers` checks if there is at least one subscriber, no matter its name, if no argument is passed.

## v3.0.0

### Breaking changes
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ For API updates and breaking changes, check the [CHANGELOG](https://github.com/g
* [.publishSync(topic, [data])](#PubSub+publishSync) ⇒ <code>boolean</code>
* [.unsubscribe(topic)](#PubSub+unsubscribe) ⇒ <code>boolean</code> &#124; <code>string</code>
* [.unsubscribeAll()](#PubSub+unsubscribeAll) ⇒ <code>[PubSub](#PubSub)</code>
* [.hasSubscribers(topic)](#PubSub+hasSubscribers) ⇒ <code>Boolean</code>
* [.hasSubscribers([topic])](#PubSub+hasSubscribers) ⇒ <code>Boolean</code>
* [.alias(aliasMap)](#PubSub+alias) ⇒ <code>[PubSub](#PubSub)</code>

<a name="new_PubSub_new"></a>
Expand Down Expand Up @@ -177,16 +177,17 @@ pubsub.unsubscribeAll();
```
<a name="PubSub+hasSubscribers"></a>

### pubSub.hasSubscribers(topic) ⇒ <code>Boolean</code>
### pubSub.hasSubscribers([topic]) ⇒ <code>Boolean</code>
Checks if there are subscribers for a specific topic.
If `topic` is not provided, checks if there is at least one subscriber.

**Kind**: instance method of <code>[PubSub](#PubSub)</code>
**Returns**: <code>Boolean</code> - Returns `true` if topic has subscribers; otherwise `false`
**Returns**: <code>Boolean</code> - Returns `true` there are subscribers; otherwise `false`
**this**: <code>{PubSub}</code>

| Param | Type | Description |
| --- | --- | --- |
| topic | <code>String</code> | The topic's name to check |
| [topic] | <code>String</code> | The topic's name to check |

**Example**
```js
Expand Down
4 changes: 2 additions & 2 deletions dist/pubsub.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/pubsub.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "PubSub",
"version": "3.0.0",
"version": "3.1.0",
"description": "Javascript implementation of the Publish/Subscribe pattern.",
"main": "src/pubsub.js",
"scripts": {
Expand Down
98 changes: 62 additions & 36 deletions src/pubsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* PubSub.js
* Javascript implementation of the Publish/Subscribe pattern.
*
* @version 3.0.0
* @version 3.1.0
* @author George Raptis <[email protected]> (georapbox.github.io)
* @homepage https://github.com/georapbox/PubSub#readme
* @repository git+https://github.com/georapbox/PubSub.git
Expand All @@ -20,14 +20,29 @@
}('PubSub', this, function () {
'use strict';

function forOwn(obj, callback, thisArg) {
var key;

for (key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
if (callback && callback.call(thisArg, obj[key], key, obj) === false) {
return;
}
}
}

return obj;
}

function alias(fn) {
return function closure() {
return this[fn].apply(this, arguments);
};
}

function deliverTopic(instance, topic, data) {
var subscribers = instance.topics[topic],
var topics = instance._pubsub_topics,
subscribers = topics[topic],
len = subscribers ? subscribers.length : 0,
currentSubscriber, token;

Expand All @@ -50,7 +65,9 @@
}

function publish(instance, topic, data, sync) {
if (!instance.topics[topic]) {
var topics = instance._pubsub_topics;

if (!topics[topic]) {
return false;
}

Expand All @@ -66,8 +83,8 @@
* @constructor PubSub
*/
function PubSub() {
this.topics = {}; // Storage for topics that can be broadcast or listened to.
this.subUid = -1; // A topic identifier.
this._pubsub_topics = {}; // Storage for topics that can be broadcast or listened to.
this._pubsub_uid = -1; // A topic identifier.
return this;
}

Expand All @@ -93,22 +110,23 @@
* });
*/
PubSub.prototype.subscribe = function (topic, callback, once) {
var token = this.subUid += 1,
var topics = this._pubsub_topics,
token = this._pubsub_uid += 1,
obj = {};

if (typeof callback !== 'function') {
throw new TypeError('When subscribing for an event, a callback function must be defined.');
}

if (!this.topics[topic]) {
this.topics[topic] = [];
if (!topics[topic]) {
topics[topic] = [];
}

obj.token = token;
obj.callback = callback;
obj.once = !!once;

this.topics[topic].push(obj);
topics[topic].push(obj);

return token;
};
Expand Down Expand Up @@ -192,26 +210,27 @@
* pubsub.unsubscribe(onUserAdd);
*/
PubSub.prototype.unsubscribe = function (topic) {
var tf = false,
var topics = this._pubsub_topics,
tf = false,
prop, len;

for (prop in this.topics) {
if (Object.hasOwnProperty.call(this.topics, prop)) {
if (this.topics[prop]) {
len = this.topics[prop].length;
for (prop in topics) {
if (Object.prototype.hasOwnProperty.call(topics, prop)) {
if (topics[prop]) {
len = topics[prop].length;

while (len) {
len -= 1;

// `topic` is a tokenized reference to the subscription.
if (this.topics[prop][len].token === topic) {
this.topics[prop].splice(len, 1);
if (topics[prop][len].token === topic) {
topics[prop].splice(len, 1);
return topic;
}

// `topic` is the event name.
if (prop === topic) {
this.topics[prop].splice(len, 1);
topics[prop].splice(len, 1);
tf = true;
}
}
Expand Down Expand Up @@ -240,24 +259,21 @@
* pubsub.unsubscribeAll();
*/
PubSub.prototype.unsubscribeAll = function () {
var prop;

for (prop in this.topics) {
if (Object.hasOwnProperty.call(this.topics, prop)) {
this.topics[prop] = [];
}
}
forOwn(this._pubsub_topics, function (topicValue, topicKey, topic) {
topic[topicKey] = [];
});

return this;
};

/**
* Checks if there are subscribers for a specific topic.
* If `topic` is not provided, checks if there is at least one subscriber.
*
* @memberof PubSub
* @this {PubSub}
* @param {String} topic The topic's name to check
* @return {Boolean} Returns `true` if topic has subscribers; otherwise `false`
* @param {String} [topic] The topic's name to check
* @return {Boolean} Returns `true` there are subscribers; otherwise `false`
* @example
*
* var pubsub = new PubSub();
Expand All @@ -269,9 +285,23 @@
* // -> true
*/
PubSub.prototype.hasSubscribers = function (topic) {
var topics = this.topics;
var topics = this._pubsub_topics,
hasSubscribers = false;

// If no arguments passed
if (topic == null) {
forOwn(topics, function (topicValue) {
if (topicValue.length > 0) {
hasSubscribers = true;
return false;
}
});

if (Object.hasOwnProperty.call(topics, topic) && topics[topic].length > 0) {
return hasSubscribers;
}

// If a topic's name is passed as argument
if (Object.prototype.hasOwnProperty.call(topics, topic) && topics[topic].length > 0) {
return true;
}

Expand All @@ -297,15 +327,11 @@
* });
*/
PubSub.prototype.alias = function (aliasMap) {
var prop;

for (prop in aliasMap) {
if (Object.hasOwnProperty.call(aliasMap, prop)) {
if (PubSub.prototype[prop]) {
PubSub.prototype[aliasMap[prop]] = alias(prop);
}
forOwn(aliasMap, function (value, key) {
if (PubSub.prototype[key]) {
PubSub.prototype[aliasMap[key]] = alias(key);
}
}
});

return this;
};
Expand Down
4 changes: 2 additions & 2 deletions tests/pubsub.specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ describe('Unsubscribe from event.', function () {
var unsub = ps.unsubscribe('example-event');

expect(unsub).toBe('example-event');
expect(ps.topics['example-event'].length).toBe(0);
expect(ps._pubsub_topics['example-event'].length).toBe(0);
});

it('Unsubscribes from event using tokenized reference to the subscription.', function () {
Expand All @@ -68,7 +68,7 @@ describe('Unsubscribe from event.', function () {
sub3 = ps.subscribe('example-event', listener);

expect(ps.unsubscribe(sub)).toBe(0);
expect(ps.topics['example-event'].length).toBe(2);
expect(ps._pubsub_topics['example-event'].length).toBe(2);
});

it('Unsubscribes from an event that was not subscribed before.', function () {
Expand Down

0 comments on commit 76a09b7

Please sign in to comment.