packages/shared/src/subscribable.ts (51 lines of code) (raw):
import { isFn } from './types'
const UNSUBSCRIBE_ID_SYMBOL = Symbol('UNSUBSCRIBE_ID_SYMBOL')
export interface ISubscriber<Payload = any> {
(payload: Payload): void | boolean
}
export class Subscribable<ExtendsType = any> {
private subscribers: {
index?: number
[key: number]: ISubscriber
} = {
index: 0,
}
dispatch<T extends ExtendsType = any>(event: T, context?: any) {
let interrupted = false
for (const key in this.subscribers) {
if (isFn(this.subscribers[key])) {
event['context'] = context
if (this.subscribers[key](event) === false) {
interrupted = true
}
}
}
return interrupted ? false : true
}
subscribe(subscriber: ISubscriber) {
let id: number
if (isFn(subscriber)) {
id = this.subscribers.index + 1
this.subscribers[id] = subscriber
this.subscribers.index++
}
const unsubscribe = () => {
this.unsubscribe(id)
}
unsubscribe[UNSUBSCRIBE_ID_SYMBOL] = id
return unsubscribe
}
unsubscribe = (id?: number | string | (() => void)) => {
if (id === undefined || id === null) {
for (const key in this.subscribers) {
this.unsubscribe(key)
}
return
}
if (!isFn(id)) {
delete this.subscribers[id]
} else {
delete this.subscribers[id[UNSUBSCRIBE_ID_SYMBOL]]
}
}
}