Skip to content

Commit

Permalink
add static method noConflict
Browse files Browse the repository at this point in the history
  • Loading branch information
georapbox committed Oct 23, 2017
1 parent 6657ea7 commit 5be8e91
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 32 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.4.0
- Add static method `PubSub.noConflict()` to roll back the global `PubSub` identifier. Used in a normal browser global namespace environment to avoid conflicts, etc.

## v3.3.0
- If there is no subscriber for a topic, delete topic property when unsubscribing. Used to leave it as an empty array before.
- The result of `subscribers` and `subscribersByTopic` methods is just a copy of the original object or array accordingly.
Expand Down
77 changes: 48 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,35 +30,34 @@ $ npm install PubSub
$ bower install georapbox.pubsub.js
```

## Changelog

For API updates and breaking changes, check the [CHANGELOG](https://github.com/georapbox/PubSub/blob/master/CHANGELOG.md).

## API

* [PubSub](#PubSub)
* [new PubSub()](#new_PubSub_new)
* [.subscribe(topic, callback, [once])](#PubSub+subscribe) ⇒ <code>number</code>
* [.subscribeOnce(topic, callback)](#PubSub+subscribeOnce) ⇒ <code>number</code>
* [.publish(topic, [data])](#PubSub+publish) ⇒ <code>boolean</code>
* [.publishSync(topic, [data])](#PubSub+publishSync) ⇒ <code>boolean</code>
* [.unsubscribe(topic)](#PubSub+unsubscribe) ⇒ <code>boolean</code> \| <code>string</code>
* [.unsubscribeAll()](#PubSub+unsubscribeAll) ⇒ <code>[PubSub](#PubSub)</code>
* [.hasSubscribers([topic])](#PubSub+hasSubscribers) ⇒ <code>boolean</code>
* [.subscribers()](#PubSub+subscribers) ⇒ <code>object</code>
* [.subscribersByTopic(topic)](#PubSub+subscribersByTopic) ⇒ <code>array</code>
* [.alias(aliasMap)](#PubSub+alias) ⇒ <code>[PubSub](#PubSub)</code>
* _instance_
* [.subscribe(topic, callback, [once])](#PubSub+subscribe) ⇒ <code>number</code>
* [.subscribeOnce(topic, callback)](#PubSub+subscribeOnce) ⇒ <code>number</code>
* [.publish(topic, [...data])](#PubSub+publish) ⇒ <code>boolean</code>
* [.publishSync(topic, [...data])](#PubSub+publishSync) ⇒ <code>boolean</code>
* [.unsubscribe(topic)](#PubSub+unsubscribe) ⇒ <code>boolean</code> \| <code>string</code>
* [.unsubscribeAll()](#PubSub+unsubscribeAll) ⇒ <code>[PubSub](#PubSub)</code>
* [.hasSubscribers([topic])](#PubSub+hasSubscribers) ⇒ <code>boolean</code>
* [.subscribers()](#PubSub+subscribers) ⇒ <code>object</code>
* [.subscribersByTopic(topic)](#PubSub+subscribersByTopic) ⇒ <code>array</code>
* [.alias(aliasMap)](#PubSub+alias) ⇒ <code>[PubSub](#PubSub)</code>
* _static_
* [.noConflict()](#PubSub.noConflict) ⇒ <code>[PubSub](#PubSub)</code>

<a name="new_PubSub_new"></a>

### new PubSub()
Creates a PubSub instance.

### Methods
## Instance Methods

<a name="PubSub+subscribe"></a>

### .subscribe(topic, callback, [once]) ⇒ <code>number</code>
### pubSub.subscribe(topic, callback, [once]) ⇒ <code>number</code>
Subscribe to events of interest with a specific topic name and a
callback function, to be executed when the topic/event is observed.

Expand All @@ -82,7 +81,7 @@ var onUserAdd = pubsub.subscribe('user_add', function (data, topic) {
```
<a name="PubSub+subscribeOnce"></a>

### .subscribeOnce(topic, callback) ⇒ <code>number</code>
### pubSub.subscribeOnce(topic, callback) ⇒ <code>number</code>
Subscribe to events of interest setting a flag
indicating the event will be published only one time.

Expand All @@ -103,7 +102,7 @@ var onUserAdd = pubsub.subscribeOnce('user_add', function (data, topic) {
```
<a name="PubSub+publish"></a>

### .publish(topic, [data]) ⇒ <code>boolean</code>
### pubSub.publish(topic, [data]) ⇒ <code>boolean</code>
Publishes a topic **asynchronously**, passing the data to its subscribers.
Asynchronous publication helps in that the originator of the topics will not be blocked while consumers process them.
For synchronous topic publication check `publishSync`.
Expand All @@ -126,7 +125,7 @@ pubsub.publish('user_add', {
```
<a name="PubSub+publishSync"></a>

### .publishSync(topic, [data]) ⇒ <code>boolean</code>
### pubSub.publishSync(topic, [data]) ⇒ <code>boolean</code>
Publishes a topic **synchronously**, passing the data to its subscribers.

**Kind**: instance method of <code>[PubSub](#PubSub)</code>
Expand All @@ -147,7 +146,7 @@ pubsub.publishSync('user_add', {
```
<a name="PubSub+unsubscribe"></a>

### .unsubscribe(topic) ⇒ <code>boolean</code> \| <code>string</code>
### pubSub.unsubscribe(topic) ⇒ <code>boolean</code> \| <code>string</code>
Unsubscribes from a specific topic, based on the topic name,
or based on a tokenized reference to the subscription.

Expand All @@ -168,7 +167,7 @@ pubsub.unsubscribe(onUserAdd);
```
<a name="PubSub+unsubscribeAll"></a>

### .unsubscribeAll() ⇒ <code>[PubSub](#PubSub)</code>
### pubSub.unsubscribeAll() ⇒ <code>[PubSub](#PubSub)</code>
Clears all subscriptions whatsoever.

**Kind**: instance method of <code>[PubSub](#PubSub)</code>
Expand All @@ -184,7 +183,7 @@ pubsub.hasSubscribers(); // -> false
```
<a name="PubSub+hasSubscribers"></a>

### .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.

Expand All @@ -207,14 +206,13 @@ pubsub.hasSubscribers('message');
```
<a name="PubSub+subscribers"></a>

### .subscribers() ⇒ <code>object</code>
### pubSub.subscribers() ⇒ <code>object</code>
Gets all the subscribers as a set of key value pairs that
represent the topic's name and the event listener(s) bound.

**NOTE**: Mutating the result of this method does not affect the real subscribers. This is for reference only.

**Kind**: instance method of <code>[PubSub](#PubSub)</code>
**Returns**: <code>object</code> - A readonly object with all subscribers.
**Note**: Mutating the result of this method does not affect the real subscribers. This is for reference only.
**Example**
```js
var pubsub = new PubSub();
Expand All @@ -228,13 +226,12 @@ pubsub.subscribers();
```
<a name="PubSub+subscribersByTopic"></a>

### .subscribersByTopic(topic) ⇒ <code>array</code>
### pubSub.subscribersByTopic(topic) ⇒ <code>array</code>
Gets subscribers for a specific topic.

**NOTE**: Mutating the result of this method does not affect the real subscribers. This is for reference only.

**Kind**: instance method of <code>[PubSub](#PubSub)</code>
**Returns**: <code>array</code> - A copy array of all subscribers for a topic if exist; otherwise an empty array
**Note**: Mutating the result of this method does not affect the real subscribers. This is for reference only.

| Param | Type | Description |
| --- | --- | --- |
Expand All @@ -259,7 +256,7 @@ pubsub.subscribersByTopic('some_message_not_existing');
```
<a name="PubSub+alias"></a>

### .alias(aliasMap) ⇒ <code>[PubSub](#PubSub)</code>
### pubSub.alias(aliasMap) ⇒ <code>[PubSub](#PubSub)</code>
Creates aliases for public methods.

**Kind**: instance method of <code>[PubSub](#PubSub)</code>
Expand All @@ -281,6 +278,24 @@ var pubsub = new PubSub().alias({
});
```

## Static methods

<a name="PubSub.noConflict"></a>

### PubSub.noConflict() ⇒ <code>[PubSub](#PubSub)</code>
Rolls back the global `PubSub` identifier and returns the current constructor function.
This can be used to keep the global namespace clean, or it can be used to have multiple simultaneous libraries
(including separate versions/copies of `PubSub`) in the same project without conflicts over the `PubSub` global identifier.

**Kind**: static method of <code>[PubSub](#PubSub)</code>
**Returns**: <code>[PubSub](#PubSub)</code> - The PubSub constructor.
**Note**: The `PubSub.noConflict()` static method only makes sense when used in a normal browser global namespace environment. It should not be used with CommonJS or AMD style modules.
**Example**
```js
var EventEmitter = PubSub.noConflict();
var emitter = new EventEmitter();
```

## Minify source code

```sh
Expand All @@ -296,6 +311,10 @@ To run the tests:
$ npm test
```

## Changelog

For API updates and breaking changes, check the [CHANGELOG](https://github.com/georapbox/PubSub/blob/master/CHANGELOG.md).

## More about Publish/Subscribe pattern

- [The Observer Pattern - Addy Osmani](https://addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjavascript)
Expand Down
37 changes: 34 additions & 3 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.3.0
* @version 3.4.0
* @author George Raptis <[email protected]> (georapbox.github.io)
* @homepage https://github.com/georapbox/PubSub#readme
* @repository https://github.com/georapbox/PubSub.git
Expand All @@ -16,11 +16,14 @@
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = definition();
} else {
context[name] = definition();
context[name] = definition(name, context);
}
}('PubSub', this, function () {
}('PubSub', this, function (name, context) {
'use strict';

var VERSION = '3.4.0';
var OLD_PUBLIC_API = (context || {})[name];

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

Expand Down Expand Up @@ -408,5 +411,33 @@
return this;
};

/**
* Rolls back the global `PubSub` identifier and returns the current constructor function.
* This can be used to keep the global namespace clean, or it can be used to have multiple simultaneous libraries
* (including separate versions/copies of `PubSub`) in the same project without conflicts over the `PubSub` global identifier.
*
* @NOTE The `PubSub.noConflict()` static method only makes sense when used in a normal browser global namespace environment.
* It should not be used with CommonJS or AMD style modules.
*
* @memberof PubSub
* @return {PubSub} The PubSub constructor.
* @example
*
* var EventEmitter = PubSub.noConflict();
* var emitter = new EventEmitter();
*/
PubSub.noConflict = function noConflict() {
if (context) {
context[name] = OLD_PUBLIC_API;
}
return PubSub;
};

/**
* PubSub version
* @type {String}
*/
PubSub.version = VERSION;

return PubSub;
}));
11 changes: 11 additions & 0 deletions tests/pubsub.specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,14 @@ describe('Ensure that listeners registered on the same topic are invoked in the
expect(arr).toEqual(['A', 'B', 'C']);
});
});

// noConflict functionality
describe('noConflict static method', function () {
it('should roll back the global PubSub identifier and return the current constructor function', function () {
var EventEmitter = PubSub.noConflict();
var emitter = new EventEmitter();

expect(PubSub).toBeUndefined();
expect(emitter instanceof EventEmitter).toBe(true);
});
});

0 comments on commit 5be8e91

Please sign in to comment.