Single Getter + Setter + Watcher function
export interface IObservable<T> extends Function {
emit(item: T): void;
subscribe(callback: (item: T) => void, noInit?: boolean): { unsubscribe: () => void }
}
export interface IObserver<T> {
emit: (value: T) => any;
}
interface ISubscription {
unsubscribe: () => any;
}
export function Observable<T>(initVal?: T): IObservable<T> {
const subscriptions: Array<IObserver<T>> = [];
let currentVal = initVal;
const subscribe = (callback: (item: T) => void, noInit: boolean): ISubscription => {
const subscription: IObserver<T> = { emit: (val: T) => callback(val) };
subscriptions.push(subscription);
if (!noInit && currentVal !== undefined) {
subscription.emit(currentVal);
}
const remove = (arr: any[], item: any) => {
const i = arr.indexOf(item);
if (i >= 0) arr.splice(i, 1);
};
const unsubscribe = () => remove(subscriptions, subscription);
return { unsubscribe: unsubscribe };
};
const emit = (val: T) => {
currentVal = val;
setTimeout(() => subscriptions.forEach(s => s.emit(val)), 0);
};
const o: IObservable<T> = (val: T) => {
if (val !== undefined) {
currentVal = val;
emit(currentVal);
}
return currentVal;
};
o.subscribe = subscribe;
o.emit = emit;
return o;
}
import { Observable } from "./Observable";
const observable = Observable("abc");
const subscribtion1 = observable.subscribe(x => console.log(`1: received ${x}`));
const subscribtion2 = observable.subscribe(x => console.log(`2: received ${x}`));
console.log("emitting");
observable.emit("A");
observable.emit("B");
observable.emit("C");
// get value
console.log("get value 1", observable());
// set value to "DEF"
observable("DEF");
console.log("get value 2", observable());
subscribtion1.unsubscribe();
setTimeout(() => {
observable.emit("D");
observable.emit("E");
observable.emit("F");
}, 100);
setTimeout(() => {
console.log("finished");
}, 1000);
const observable = (initVal) => {
const subscriptions = [];
let currentVal = initVal;
let isEmitting = false;
let emitAfter = null;
const subscribe = (callback, noInit) => {
var subscription = {};
subscription.emit = (val) => callback(val);
subscriptions.push(subscription);
if (!noInit) {
subscription.emit(currentVal);
}
const remove = (arr, item) => {
const i = arr.indexOf(item);
if (i >= 0) arr.splice(i, 1);
};
const unsubscribe = () => remove(subscriptions, subscription);
return { unsubscribe: unsubscribe };
};
const emit = (val) => {
if (isEmitting) {
emitAfter = () => o.emit(val);
return;
}
isEmitting = true;
setTimeout(() => {
subscriptions.forEach(s => s.emit(val));
isEmitting = false;
if (emitAfter) {
emitAfter();
emitAfter = null;
}
}, 0);
};
const o = (val) => {
if (val !== undefined) {
currentVal = val;
emit(currentVal);
}
return currentVal;
};
o.subscribe = subscribe;
return o;
};
module.exports = observable;
177400cookie-checkTypescript / Javascript: Observable