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