@benzinga/subscribable v2.0.10
Subscribable
This Project is Made Possible thanks to
The Subscribable package is a simple page that allows you to have the ability to make you class subscribable allowing for events to be dispatched to subscribers. This is done simply by inheriting the Subscribable class.
Making a basic Subscribable
import {
Subscribable,
Subscription,
SubscribableEvent,
} from '@benzinga/subscribable';
interface SetAddEvents extends SubscribableEvent<'add'> { // one of the events that can be dispatched
item: number;
}
interface SetRemoveEvents { // second event that can be dispatched as you can see you don't have to implement SubscribableEvent directly all SubscribableEvent is doing is simply adding type key with the value given
type: 'remove';
item: number;
}
type SetEvents = SetAddEvents | SetRemoveEvents; // all the events that can be fired by the subscribable
class SetSubscribable extends Subscribable<SetEvents> { // extending the subscribable and telling the subscribable when events can be fired
private items = new Set<number>();
public add = (num: number ): void => {
this.items.add(num);
this.dispatch({type: 'add', item: num}); // fire out the event inherited from Subscribable
}
public remove = (num: number ): void => {
this.items.delete(num);
this.dispatch({type: 'remove', item: num}); // fire out the event inherited from Subscribable
}
}
type SetSubscription = ReturnType<SetSubscribable['subscribe']>; // this is a helper type that represents value returned from theUsing a basic Subscribable
import SetSubscribable from './set';
const set = new SetSubscribable(); // create a new instance
const setSubscribe1 = set.subscribe(event => { // subscribe to events
switch (event.type) {
case 'add':
console.log(`added ${event.item}`);
break;
case 'remove':
console.log(`removed ${event.item}`);
break;
}
})
const setSubscribe2: SetSubscription = set.subscribe(event => { // subscribe to events
switch (event.type) {
case 'add':
console.log(`included ${event.item}`);
break;
case 'remove':
console.log(`erased ${event.item}`);
break;
}
})
console.log('start');
set.add(1);
set.remove(1);
setSubscribe1.unsubscribe(); // unsubscribe the first subscription
console.log('unsubscribe');
set.add(2);
set.remove(2);
setSubscribe2.update(event => console.log('update')); // update the callback of the subscription
set.add(3);
set.remove(3);
setSubscribe2.unsubscribe(); // unsubscribe the second subscription
console.log('end');this will result in the following output
[LOG]: "start"
[LOG]: "added 1"
[LOG]: "included 1"
[LOG]: "removed 1"
[LOG]: "erased 1"
[LOG]: "unsubscribe"
[LOG]: "included 2"
[LOG]: "erased 2"
[LOG]: "update"
[LOG]: "update"
[LOG]: "end"Class Subscription
The Subscription class takes a generics as input.
Events: is simply the event that will be fired as seen be the example above
class SetSubscribable extends Subscription<SetEvents>dispatch
protected dispatch(event : Events) => void- This is a protected function that allows the class to fire/dispatch out new events.
subscribe
public subscribe(callback: (event: Events) => void, ..._args: readonly unknown[]) => Subscription<Events>- This is a public function this is how others can subscribe to the events. It will return a
Subscriptionwhich is used to bothunsubscribeandupdatethe callback.
onFirstSubscription
protected onFirstSubscription = () => void;- the class inheriting from
Subscribablecan also implementonFirstSubscription. this is useful if you want to wait for a subscriber before initializing something.
onZeroSubscriptions
protected onZeroSubscriptions = () => void;- the class inheriting from
Subscribablecan also implementonZeroSubscriptions. this is useful if you want to do some cleaning when there are no subscribers.
onSubscribe
protected onSubscribe = (..._args: readonly unknown[]): void;- the
onSubscribeallows you to run any kind of logic you want when a new Subscriber is added.
onUnsubscribe
protected onUnsubscribe = () => void;- the class inheriting from
Subscribablecan also implementonUnsubscribe. this is useful if you want to keep track of the number of subscribers. you can increment the number of subscribers using theconstructorcallback and decrement here.
Class ExtendedSubscription
The ExtendedSubscription inherits from Subscription the class takes two generics with the second generic.
Events: is simply the event that will be fired as seen be the example aboveExtension: indicates what the subscription will be extended with. for exampleinterface SetExtends { add: (num: number ) => void remove: (num: number ) => void } class SetSubscribable extends ExtendedSubscription<SetEvents, SetExtends>this will now indicate the returned Subscription will have
addandremovefunction that are callable. to accomplish this you will need to returnSetExtendsin theonSubscriptionevent. more on that later.
Class Subscription vs ExtendedSubscription
ExtendedSubscription is simply an extension of the Subscription in which the subscribe function has been overloaded to add the data returned from onSubscription to be added to the return of the subscription.
subscribe
public subscribe(callback: (event: Events) => void, ..._args: readonly unknown[]) => Subscription<Events, Extension>- This is a public function this is how others can subscribe to the events. It will return a
Subscriptionwhich is used to bothunsubscribeandupdatethe callback. it will also include theExtendedfunctions to the return.
onSubscribe
protected onSubscribe = (..._args: readonly unknown[]): Extensionthe
onSubscribeallows you to run any kind of logic you want when a new Subscriber is added but a return of typeExtensionis required.interface SetExtends { add: (num: number ) => void remove: (num: number ) => void } class SetSubscribable extends ExtendedSubscription<SetEvents, SetExtends> { onSubscribe = () => ({ // remember that () => ({}) is shorthand for () => { return {}} open: this.open, remove: this.remove, }) }this will allow you to call
addandremoveon theSubscriptionreturned after callingsubscribealso if you only want subscribers to SetSubscribable to
addandremoveitems you can simply make themprivatein the class. making the only way to assess the functions is throughSubscription.
Making a basic ExtendedSubscription
import {
Subscribable,
Subscription,
SubscribableEvent,
} from '@benzinga/subscribable';
interface SetAddEvents extends SubscribableEvent<'add'> { // one of the events that can be dispatched
item: number;
}
interface SetRemoveEvents { // second event that can be dispatched as you can see you don't have to implement SubscribableEvent directly all SubscribableEvent is doing is simply adding type key with the value given
type: 'remove';
item: number;
}
type SetEvents = SetAddEvents | SetRemoveEvents; // all the events that can be fired by the subscribable
interface SetSubscribableFunctions {
add: (num: number) => void;
remove: (num: number) => void
}
class SetSubscribable extends ExtendedSubscribable<SetEvents, SetSubscribableFunctions> { // extending the subscribable and telling the subscribable when events can be fired
private items = new Set<number>();
private add = (num: number ): void => { // note i made add protected to make sure that only subscribers can add
this.items.add(num);
this.dispatch({type: 'add', item: num}); // fire out the event inherited from Subscribable
}
private remove = (num: number ): void => { // note i made add protected to make sure that only subscribers can remove
this.items.delete(num);
this.dispatch({type: 'remove', item: num}); // fire out the event inherited from Subscribable
}
protected onSubscribe = () => ({
add: this.add,
remove: this.remove,
})
}
type SetSubscription = ReturnType<SetSubscribable['subscribe']>; // this is a helper type that represents value returned from theUsing a basic Subscribable
import SetSubscribable from './set';
const set = new SetSubscribable(); // create a new instance
const setSubscribe1 = set.subscribe(event => { // subscribe to events
switch (event.type) {
case 'add':
console.log(`added ${event.item}`);
break;
case 'remove':
console.log(`removed ${event.item}`);
break;
}
})
const setSubscribe2: SetSubscription = set.subscribe(event => { // subscribe to events
switch (event.type) {
case 'add':
console.log(`included ${event.item}`);
break;
case 'remove':
console.log(`erased ${event.item}`);
break;
}
})
console.log('start');
setSubscribe1.add(1);
setSubscribe1.remove(1);
setSubscribe1.unsubscribe(); // unsubscribe the first subscription
console.log('unsubscribe');
setSubscribe1.add(2);
setSubscribe1.remove(2);
setSubscribe2.update(event => console.log('update')); // update the callback of the subscription
setSubscribe2.add(3);
setSubscribe2.remove(3);
setSubscribe2.unsubscribe(); // unsubscribe the second subscription
console.log('end');utils-subscribable
This library was generated with Nx.
Running unit tests
Run nx test utils-subscribable to execute the unit tests via Jest.