Skip to content

Instantly share code, notes, and snippets.

@thomaswilburn
Created December 5, 2023 21:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save thomaswilburn/c6dc0036f75f94eefd8e17d0fa79b36c to your computer and use it in GitHub Desktop.
Save thomaswilburn/c6dc0036f75f94eefd8e17d0fa79b36c to your computer and use it in GitHub Desktop.
Classy signals
var tracking = [];
var pending = new Set();
function anticipate(fn) {
pending.add(fn);
requestAnimationFrame(() => {
for (var p of pending) p();
pending.clear();
});
}
class Signal {
#value = undefined;
#watchers = new Set();
constructor(value) {
this.#value = value;
}
get value() {
var active = tracking.at(-1);
if (active) {
this.#watchers.add(active);
}
return this.#value;
}
set value(value) {
if (value == this.#value) return
this.#value = value;
for (var watcher of this.#watchers) {
anticipate(watcher);
}
}
destroy() {
this.#watchers.clear();
}
}
class Derived extends Signal {
#value = undefined;
constructor(fn) {
super();
trackExecution(() => {
this.value = fn();
});
}
}
function trackExecution(fn) {
tracking.push(fn);
fn();
tracking.pop();
}
var a = new Signal(0);
var b = new Signal(0);
var sum = new Derived(function() {
console.info("sum!");
return a.value + b.value;
});
var sumSquared = new Derived(function() {
console.info("square!");
return sum.value ** 2;
});
trackExecution(function() {
console.info("tracked!")
console.log("a + b", sum.value);
console.log("sum^2", sumSquared.value);
});
console.log("a = 1");
a.value = 1;
console.log("b = 3");
b.value = 3;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment