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