Timothy Farrell 4c20e1400e Add stream type to frptools.
(prettier got ahold of this commit)
2018-05-31 15:48:18 -05:00

52 lines
1.3 KiB
JavaScript

import { id, registerFire, registerSubscriptions, call } from './util.js';
export function stream(fn, dependencies = [], hash = id) {
let subscribers = [];
let isDirty = true;
let val;
let oldId;
// Compute new value, call subscribers if changed.
const accessor = async function _computed() {
if (isDirty) {
const newVal = await fn.apply(null, await Promise.all(dependencies.map(call)));
isDirty = false;
const newId = hash(newVal);
if (oldId !== newId) {
oldId = newId;
val = newVal;
accessor.fire(val);
}
}
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;
}