Typescript / Javascript: Observable

Date: 2019-01-16

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;
17740cookie-checkTypescript / Javascript: Observable