@fbltd/async
Version:
Miscellaneous async utils
45 lines (44 loc) • 1.85 kB
JavaScript
import { Dependency } from "../../dependency.js";
import { symAI } from "../../../constants.js";
import { runFnWithDepCollection } from "./utils.js";
export function reaction(fn, config) {
let { result, deps } = runFnWithDepCollection(fn);
const dep = new Dependency(result, config);
async function subscribe() {
const stream = { [symAI]: () => {
let depsArray;
let beforeValues;
let obj = {
next: async () => {
depsArray = Array.from(deps);
beforeValues = depsArray.map(dep => dep.value_unsafe);
const promises = depsArray.map(dep => dep.next());
promises.push(dep.disposePromise);
await Promise.race(promises);
if (dep.done)
return { done: true };
let shouldRun = depsArray.some((dep, i) => dep.value_unsafe !== beforeValues[i]);
if (shouldRun) {
({ result, deps } = runFnWithDepCollection(fn));
return { done: false, value: result };
}
else {
for (let dep of deps) {
if (dep.done)
deps.delete(dep);
}
if (!deps.size)
return { done: true };
return obj.next();
}
}
};
return obj;
} };
for await (let value of stream) {
dep.value = value;
}
}
subscribe().then(() => dep.dispose());
return dep;
}