This repository has been archived on 2020-09-01. You can view files and clone it, but cannot push or open issues or pull requests.
reactimal/src/computed.js

57 lines
1.5 KiB
JavaScript

import { id, registerFire, registerSubscriptions, call } from './util.js';
export const hashableComputed = hash => (fn, dependencies = []) => {
let subscribers = [];
let isDirty = true;
let val;
let oldId;
const params = dependencies.map(d => (d._lock ? d._lock : d));
const unlockableDeps = dependencies.map(d => d._unlock).filter(id);
// Compute new value, call subscribers if changed.
const accessor = function _computed() {
if (isDirty) {
const newVal = fn.apply(null, params.map(call));
isDirty = false;
const newId = hash(newVal);
if (oldId !== newId) {
oldId = newId;
val = newVal;
accessor._fire(val);
}
unlockableDeps.forEach(call);
}
return val;
};
// Add child nodes to the logic graph (value-based)
accessor.subscribe = registerSubscriptions(subscribers);
accessor._fire = registerFire(subscribers);
// Receive dirty flag from parent logic node (dependency). Pass it down.
accessor._setDirty = function setDirty() {
if (!isDirty) {
isDirty = true;
subscribers.forEach(s => s._setDirty && s._setDirty());
}
return subscribers.length && accessor;
};
// Remove this node from the logic graph completely
accessor.detach = () => {
subscribers = [];
dependentSubscriptions.forEach(call);
};
// Remove child nodes from the logic graph
accessor.unsubscribeAll = () => {
subscribers = [];
};
const dependentSubscriptions = dependencies.map(d => d.subscribe(accessor._setDirty));
return accessor;
};
export const computed = hashableComputed(id);