Skip to content

Instantly share code, notes, and snippets.

@crashmax-dev
Last active April 25, 2023 13:06
Show Gist options
  • Save crashmax-dev/b193419ef2e865f44faf017d6a8db84c to your computer and use it in GitHub Desktop.
Save crashmax-dev/b193419ef2e865f44faf017d6a8db84c to your computer and use it in GitHub Desktop.
type Data = Record<string, any>
type KeyOf<T> = Extract<keyof T, string>
type Listener<T = any> = (value: T, action: ObserveAction) => void
enum ObserveAction {
Read = 'read',
Write = 'write'
}
class ObserveValue<T extends Data> {
private readonly data: T;
private readonly listeners = new Map<string, Listener[]>()
constructor(initialData: T) {
this.data = initialData
}
private getListenersByKey<Key extends KeyOf<T>>(key: Key): Listener[] {
return this.listeners.get(key) ?? []
}
private invokeListeners<Key extends KeyOf<T>>(key: Key, value: T[Key], action: ObserveAction): void {
const listeners = this.getListenersByKey(key)
if (!listeners.length) return
for (const listener of listeners) {
listener(value, action)
}
}
on<Key extends KeyOf<T>>(key: Key, callback: Listener<T[Key]>): void {
const listeners = this.getListenersByKey(key)
listeners.push(callback)
this.listeners.set(key, listeners)
}
off<Key extends KeyOf<T>>(key: Key, callback: Listener<T[Key]>): void {
const listeners = this.getListenersByKey(key)
if (!listeners.length) return
const newListeners = listeners.filter((listener) => listener !== callback)
this.listeners.set(key, newListeners)
}
write<Key extends KeyOf<T>>(key: Key, value: T[Key]): void {
this.data[key] = value
this.invokeListeners(key, value, ObserveAction.Write)
}
read<Key extends KeyOf<T>>(key: Key): void {
const value = this.data[key]
this.invokeListeners(key, value, ObserveAction.Read)
}
}
const observe = new ObserveValue({
id: 1,
login: 'John'
})
function observeLogin(value: string, action: ObserveAction): void {
console.log(action, value)
}
observe.on('id', (value, action) => console.log(action, value))
observe.on('login', observeLogin)
observe.write('id', 2)
observe.write('login', 'John Doe')
observe.read('id')
observe.off('login', observeLogin)
observe.read('login')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment