Remove Tappable and Emitter

This commit is contained in:
Aria Minaei 2022-12-01 15:16:37 +01:00
parent 391958f5cf
commit 867cf51acb
4 changed files with 1 additions and 188 deletions

View file

@ -254,7 +254,7 @@ class PrismInstance<V> implements Prism<V> {
}
/**
* Returns a tappable that fires every time the prism's state goes from `fresh-\>stale.`
* Calls `callback` every time the prism's state goes from `fresh-\>stale.` Returns an `unsubscribe()` function.
*/
onStale(callback: () => void): VoidFn {
const untap = () => {

View file

@ -1,19 +0,0 @@
import Emitter from './Emitter'
describe('DataVerse.Emitter', () => {
it('should work', () => {
const e: Emitter<string> = new Emitter()
e.emit('no one will see this')
e.emit('nor this')
const tappedEvents: string[] = []
const untap = e.tappable.tap((payload) => {
tappedEvents.push(payload)
})
e.emit('foo')
e.emit('bar')
untap()
e.emit('baz')
expect(tappedEvents).toMatchObject(['foo', 'bar'])
})
})

View file

@ -1,76 +0,0 @@
import Tappable from './Tappable'
type Tapper<V> = (v: V) => void
type Untap = () => void
/**
* An event emitter. Emit events that others can tap (subscribe to).
*/
export default class Emitter<V> {
private _tappers: Map<any, (v: V) => void>
private _lastTapperId: number
private _onNumberOfTappersChangeListener: undefined | ((n: number) => void)
/**
* The Tappable associated with this emitter. You can use this to tap (subscribe to) events emitted.
*/
readonly tappable: Tappable<V>
constructor() {
this._lastTapperId = 0
this._tappers = new Map()
this.tappable = new Tappable({
tapToSource: (cb: Tapper<V>) => this._tap(cb),
})
}
_tap(cb: Tapper<V>): Untap {
const tapperId = this._lastTapperId++
this._tappers.set(tapperId, cb)
this._onNumberOfTappersChangeListener?.(this._tappers.size)
return () => {
this._removeTapperById(tapperId)
}
}
_removeTapperById(id: number) {
const oldSize = this._tappers.size
this._tappers.delete(id)
const newSize = this._tappers.size
if (oldSize !== newSize) {
this._onNumberOfTappersChangeListener?.(newSize)
}
}
/**
* Emit a value.
*
* @param payload - The value to be emitted.
*/
emit(payload: V) {
for (const cb of this._tappers.values()) {
cb(payload)
}
}
/**
* Checks whether the emitter has tappers (subscribers).
*/
hasTappers() {
return this._tappers.size !== 0
}
/**
* Calls callback when the number of tappers (subscribers) changes.
*
* @example
* ```ts
* emitter.onNumberOfTappersChange((n) => {
* console.log("number of tappers changed:", n)
* })
* ```
*/
onNumberOfTappersChange(cb: (n: number) => void) {
this._onNumberOfTappersChangeListener = cb
}
}

View file

@ -1,92 +0,0 @@
type Untap = () => void
type UntapFromSource = () => void
interface IProps<V> {
tapToSource: (cb: (payload: V) => void) => UntapFromSource
}
type Listener<V> = ((v: V) => void) | (() => void)
/**
* Represents a data-source that can be tapped (subscribed to).
*/
export default class Tappable<V> {
private _props: IProps<V>
private _tappers: Map<number, {bivarianceHack(v: V): void}['bivarianceHack']>
private _untapFromSource: null | UntapFromSource
private _lastTapperId: number
private _untapFromSourceTimeout: null | NodeJS.Timer = null
constructor(props: IProps<V>) {
this._lastTapperId = 0
this._untapFromSource = null
this._props = props
this._tappers = new Map()
}
private _check() {
if (this._untapFromSource) {
if (this._tappers.size === 0) {
this._scheduleToUntapFromSource()
/*
* this._untapFromSource()
* this._untapFromSource = null
*/
}
} else {
if (this._tappers.size !== 0) {
this._untapFromSource = this._props.tapToSource(this._cb)
}
}
}
private _scheduleToUntapFromSource() {
if (this._untapFromSourceTimeout !== null) return
this._untapFromSourceTimeout = setTimeout(() => {
this._untapFromSourceTimeout = null
if (this._tappers.size === 0) {
this._untapFromSource!()
this._untapFromSource = null
}
}, 0)
}
private _cb: any = (arg: any): void => {
for (const cb of this._tappers.values()) {
cb(arg)
}
}
/**
* Tap (subscribe to) the data source.
*
* @param cb - The callback to be called on a change.
*/
tap(cb: Listener<V>): Untap {
const tapperId = this._lastTapperId++
this._tappers.set(tapperId, cb)
this._check()
return () => {
this._removeTapperById(tapperId)
}
}
private _removeTapperById(id: number) {
this._tappers.delete(id)
this._check()
}
// /**
// * @deprecated
// */
// map<T>(transform: {bivarianceHack(v: V): T}['bivarianceHack']): Tappable<T> {
// return new Tappable({
// tapToSource: (cb: (v: T) => void) => {
// return this.tap((v: $IntentionalAny) => {
// return cb(transform(v))
// })
// },
// })
// }
}