Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PubSub and ReactiveStore utilities #486

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions package-lock.json

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

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
"./components/view-toggle.js": "./src/components/view-toggle/view-toggle.js",
"./controllers/computed-value.js": "./src/controllers/computed-values/computed-value.js",
"./controllers/computed-values.js": "./src/controllers/computed-values/computed-values.js",
"./controllers/language-listener.js": "./src/controllers/language-listener/language-listener.js"
"./controllers/language-listener.js": "./src/controllers/language-listener/language-listener.js",
"./utilities/pub-sub.js": "./src/utilities/pub-sub/pub-sub.js",
"./utilities/reactive-store.js": "./src/utilities/reactive-store/reactive-store.js"
},
"scripts": {
"langs:sync": "mfv add-missing && mfv remove-extraneous",
Expand Down Expand Up @@ -52,6 +54,7 @@
},
"dependencies": {
"@brightspace-ui/core": "^3",
"@lit/context": "^1.1.3",
"lit": "^3"
},
"version": "2.4.1"
Expand Down
76 changes: 76 additions & 0 deletions src/utilities/pub-sub/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# PubSub

A simple class implementation of the publish-subscribe model.

## Simple Example

```js
import PubSub from '@brightspace-ui/labs/utilites/pub-sub.js';

// Instantiate the PubSub class
const myPubSub = new PubSub();

// Register subscribers
const subscriber1 = (message) => console.log('Subscriber 1 received: ', message);
const subscriber2 = (message) => console.log('Subscriber 2 received: ', message);
myPubSub.subscribe(subscriber1);
myPubSub.subscribe(subscriber2);

// Publish messages to subscribers
myPubSub.publish('Hello!');
// Console: Subscriber 1 received: Hello!
// Console: Subscriber 2 received: Hello!

// Unsubscribe
myPubSub.unsubscribe(subscriber1);
myPubSub.unsubscribe(subscriber2);
```

## Instance Methods

### Constructor

The constructor takes no arguments.

### `clear()`

The `clear` method unsubscribes all subscribed callback functions. Subscriber callback functions are not called at this time, just removed.

This method accepts no arguments and returns no values.

### `publish(...args)`

The `publish` method is used to publish messages/data to all subscribed callbacks. All subscribed callback functions are called in subscription order with the same arguments passed to `publish`.

| Parameter Name | Type | Description | Required |
|---|---|---|---|
| `...args` | Any | The arguments to be passed to subscriber callback functions when called. | No |

`publish` returns no values.

### `subscribe(callback, initialize = false)`

The `subscribe` method is used to subscribe a callback function for future published messages.

If the callback being subscribed is already subscribed, nothing will change and it will still only be called once when messages are published.

By default, a subscribed callback function won't be called until a message is published, but if the `initialize` argument is set to `true` and the `PubSub` instance has published at least once, then the callback function will be immediately called after subscription with the last published arguments.

| Parameter Name | Type | Description | Required | Default Value |
|---|---|---|---|---|
| `callback` | Function | The callback function to be called when messages are published. | True | |
| `initialize` | Boolean | Whether or not to immedately call the callback function with the last published values. | False | `false` |

`subscribe` returns no values.

### `unsubscribe(callback)`

The `unsubscribe` method is used to remove a callback function from the collection of subscribers so it no longer receives future published messages.

If the callback function passed in does not match a currently subscribed function, nothing happens.

| Parameter Name | Type | Description | Required |
|---|---|---|---|
| `callback` | Function | The callback function to remove from the subscribers. | True |

`unsubscribe` returns no values.
33 changes: 33 additions & 0 deletions src/utilities/pub-sub/pub-sub.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
A simple pub-sub implementation. It allows for subscribing to the class and publishing to all subscribers.
*/
export default class PubSub {
constructor() {
this._subscribers = new Map();
this._hasTriggered = false;
this._previousArgs = [];
}

clear() {
this._subscribers.clear();
}

publish(...args) {
this._subscribers.forEach(callback => callback(...args));
this._hasTriggered = true;
this._previousArgs = args;
}

// If initialize is true and publish has been called at least once, the callback will be called
// immediately with the last published arguments.
subscribe(callback, initialize = false) {
this._subscribers.set(callback, callback);
if (this._hasTriggered && initialize) {
callback(...this._previousArgs);
}
}

unsubscribe(callback) {
this._subscribers.delete(callback);
}
}
Loading
Loading