From 912398f9dc99898d384df2ec169626da52bbfe21 Mon Sep 17 00:00:00 2001 From: Gonzalo Ruiz de Villa Date: Tue, 4 Apr 2023 16:31:34 +0200 Subject: [PATCH] Create signals_v3.js --- signals_v3.js | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 signals_v3.js diff --git a/signals_v3.js b/signals_v3.js new file mode 100644 index 0000000..d8dbf60 --- /dev/null +++ b/signals_v3.js @@ -0,0 +1,111 @@ +// Global variable to keep track of the currently accessed computed or effect +let currentAccessed = null; + +class Signal { + constructor(initialValue) { + this._value = initialValue; + this._dependents = []; + } + + get value() { + if (currentAccessed) { + this._addDependent(currentAccessed); + } + return this._value; + } + + set value(newValue) { + if (this._value !== newValue) { + this._value = newValue; + this._notifyDependents(); + } + } + + _addDependent(dependent) { + if (!this._dependents.includes(dependent)) { + this._dependents.push(dependent); + } + } + + _removeDependent(dependent) { + this._dependents = this._dependents.filter((dep) => dep !== dependent); + } + + _notifyDependents() { + for (const dependent of this._dependents) { + dependent._update(); + } + } +} + +class Computed { + constructor(computeFn) { + this._computeFn = computeFn; + this._value = undefined; + this._isStale = true; + } + + get value() { + if (this._isStale) { + currentAccessed = this; + this._recomputeValue(); + currentAccessed = null; + } + return this._value; + } + + _recomputeValue() { + this._value = this._computeFn(); + this._isStale = false; + } + + _update() { + this._isStale = true; + } +} + +class Effect { + constructor(effectFn) { + this._effectFn = effectFn; + this._isStale = true; + this._execute(); + } + + _execute() { + if (this._isStale) { + currentAccessed = this; + this._effectFn(); + currentAccessed = null; + } + } + + _update() { + this._isStale = true; + this._execute(); + } +} + +function createSignal(initialValue) { + return new Signal(initialValue); +} + +function createComputed(computeFn) { + return new Computed(computeFn); +} + +function createEffect(effectFn) { + return new Effect(effectFn); +} + +// Creating signals +const count = createSignal(0); +const multiplier = createSignal(2); + +// Creating an effect +createEffect(() => { + console.log("Effect called: Count is", count.value, "and multiplier is", multiplier.value); +}); + +// Changing signal values +count.value = 1; +multiplier.value = 3;