Add observable pattern implementation with Subject and ReadOnlySubject classes
- Introduced Subject class for managing state and notifying listeners - Added ReadOnlySubject class to provide read-only access to Subject values - Created assertUnreachable utility function for unreachable code handling - Updated observables index file to export Subject and ReadOnlySubject
This commit is contained in:
3
src/lang/assertUnreachable.ts
Normal file
3
src/lang/assertUnreachable.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export default function assertUnreachable(x: never): never {
|
||||||
|
throw new Error(`Unreachable code [${x}]`);
|
||||||
|
}
|
||||||
18
src/lang/observables/ReadOnlySubject.ts
Normal file
18
src/lang/observables/ReadOnlySubject.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import Disposable from '../disposables/Disposable';
|
||||||
|
import Subject from './Subject';
|
||||||
|
|
||||||
|
export default class ReadOnlySubject<T> {
|
||||||
|
private readonly _subject: Subject<T>;
|
||||||
|
|
||||||
|
constructor(subject: Subject<T>) {
|
||||||
|
this._subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
get value(): T {
|
||||||
|
return this._subject.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public subscribe(listener: (value: T) => void): Disposable {
|
||||||
|
return this._subject.subscribe(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/lang/observables/Subject.ts
Normal file
39
src/lang/observables/Subject.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import Disposable from '../disposables/Disposable';
|
||||||
|
|
||||||
|
export default class Subject<T> {
|
||||||
|
private readonly _listeners: Array<(value: T) => void> = [];
|
||||||
|
private _value: T;
|
||||||
|
|
||||||
|
constructor(value: T) {
|
||||||
|
this._value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set value(value: T) {
|
||||||
|
if (this._value === value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._value = value;
|
||||||
|
this.notifyListeners(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get value(): T {
|
||||||
|
return this._value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public subscribe(listener: (value: T) => void): Disposable {
|
||||||
|
const listenerIndex = this._listeners.push(listener);
|
||||||
|
|
||||||
|
listener(this.value);
|
||||||
|
|
||||||
|
return new Disposable(() => {
|
||||||
|
this._listeners.splice(listenerIndex, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private notifyListeners(value: T): void {
|
||||||
|
for (const listener of this._listeners) {
|
||||||
|
listener(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/lang/observables/index.ts
Normal file
4
src/lang/observables/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import Subject from './Subject';
|
||||||
|
import ReadOnlySubject from './ReadOnlySubject';
|
||||||
|
|
||||||
|
export {Subject, ReadOnlySubject};
|
||||||
Reference in New Issue
Block a user