{"id":1774,"date":"2019-01-16T10:00:17","date_gmt":"2019-01-16T09:00:17","guid":{"rendered":"https:\/\/solidt.eu\/site\/?p=1774"},"modified":"2022-08-25T09:38:42","modified_gmt":"2022-08-25T08:38:42","slug":"javascript-observable","status":"publish","type":"post","link":"https:\/\/solidt.eu\/site\/javascript-observable\/","title":{"rendered":"Typescript \/ Javascript: Observable"},"content":{"rendered":"\n<p>Single Getter + Setter + Watcher function<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">export interface IObservable&lt;T> extends Function {\n    emit(item: T): void;\n    subscribe(callback: (item: T) => void, noInit?: boolean): { unsubscribe: () => void }\n}\n\nexport interface IObserver&lt;T> {\n    emit: (value: T) => any;\n}\n\ninterface ISubscription {\n    unsubscribe: () => any;\n}\n\nexport function Observable&lt;T>(initVal?: T): IObservable&lt;T> {\n    const subscriptions: Array&lt;IObserver&lt;T>> = [];\n    let currentVal = initVal;\n    const subscribe = (callback: (item: T) => void, noInit: boolean): ISubscription => {\n        const subscription: IObserver&lt;T> = { emit: (val: T) => callback(val) };\n        subscriptions.push(subscription);\n        if (!noInit &amp;&amp; currentVal !== undefined) {\n            subscription.emit(currentVal);\n        }\n        const remove = (arr: any[], item: any) => {\n            const i = arr.indexOf(item);\n            if (i >= 0) arr.splice(i, 1);\n        };\n        const unsubscribe = () => remove(subscriptions, subscription);\n        return { unsubscribe: unsubscribe };\n    };\n    const emit = (val: T) => {\n        currentVal = val;\n        setTimeout(() => subscriptions.forEach(s => s.emit(val)), 0);\n    };\n    const o: IObservable&lt;T> = (val: T) => {\n        if (val !== undefined) {\n            currentVal = val;\n            emit(currentVal);\n        }\n        return currentVal;\n    };\n    o.subscribe = subscribe;\n    o.emit = emit;\n    return o;\n}\n<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import { Observable } from \".\/Observable\";\n\nconst observable = Observable(\"abc\");\nconst subscribtion1 = observable.subscribe(x => console.log(`1: received ${x}`));\nconst subscribtion2 = observable.subscribe(x => console.log(`2: received ${x}`));\n\nconsole.log(\"emitting\");\n\nobservable.emit(\"A\");\nobservable.emit(\"B\");\nobservable.emit(\"C\");\n\n\/\/ get value\nconsole.log(\"get value 1\", observable());\n\/\/ set value to \"DEF\"\nobservable(\"DEF\");\nconsole.log(\"get value 2\", observable());\n\nsubscribtion1.unsubscribe();\n\nsetTimeout(() => {\n    observable.emit(\"D\");\n    observable.emit(\"E\");\n    observable.emit(\"F\");\n}, 100);\n\nsetTimeout(() => {\n    console.log(\"finished\");\n}, 1000);<\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>const observable = (initVal) =&gt; {\n    const subscriptions = &#91;];\n    let currentVal = initVal;\n    let isEmitting = false;\n    let emitAfter = null;\n    const subscribe = (callback, noInit) =&gt; {\n        var subscription = {};\n        subscription.emit = (val) =&gt; callback(val);\n        subscriptions.push(subscription);\n        if (!noInit) {\n            subscription.emit(currentVal);\n        }\n        const remove = (arr, item) =&gt; {\n            const i = arr.indexOf(item);\n            if (i &gt;= 0) arr.splice(i, 1);\n        };\n        const unsubscribe = () =&gt; remove(subscriptions, subscription);\n        return { unsubscribe: unsubscribe };\n    };\n    const emit = (val) =&gt; {\n        if (isEmitting) {\n            emitAfter = () =&gt; o.emit(val);\n            return;\n        }\n        isEmitting = true;\n        setTimeout(() =&gt; {\n            subscriptions.forEach(s =&gt; s.emit(val));\n            isEmitting = false;\n            if (emitAfter) {\n                emitAfter();\n                emitAfter = null;\n            }\n        }, 0);\n    };\n    const o = (val) =&gt; {\n        if (val !== undefined) {\n            currentVal = val;\n            emit(currentVal);\n        }\n        return currentVal;\n    };\n    o.subscribe = subscribe;\n    return o;\n};\n\nmodule.exports = observable;<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Single Getter + Setter + Watcher function<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[5,4,1],"tags":[],"class_list":["post-1774","post","type-post","status-publish","format-standard","hentry","category-javascript","category-programming","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/1774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/comments?post=1774"}],"version-history":[{"count":5,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/1774\/revisions"}],"predecessor-version":[{"id":6611,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/posts\/1774\/revisions\/6611"}],"wp:attachment":[{"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/media?parent=1774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/categories?post=1774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/solidt.eu\/site\/wp-json\/wp\/v2\/tags?post=1774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}