Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | 18x 128x 287x 287x 283x 283x 128x 224x 224x 224x 99x 139x 224x 224x 224x 224x 128x | import { type ReadableLike, type Config, type Get, type OwnedReadable } from "./interface";
import { ReadableImpl } from "./readable";
import { getReadable } from "./utils";
export interface ComputeFn<TValue = any> {
(get: Get): TValue;
}
/**
* Computes a derived value based on other Readables.
*
* @category Derivations
* @param fn - The function that computes the value.
* @param config - Optional custom {@link Config}.
* @returns An {@link OwnedReadable} that computes its value based on other Readables.
*
* @example
* ```ts
* import { compute, writable, reactiveMap } from "@embra/reactivity";
*
* const v1$ = writable(0);
* const v2$ = writable(1);
* const map$ = reactiveMap([["s", 42]]);
*
* const sum$ = compute(get => get(v1$) + get(v2$) + get(map$).get("s") || 0);
* ```
*/
export const compute = <TValue>(fn: ComputeFn<TValue>, config?: Config<TValue>): OwnedReadable<TValue> => {
let running: boolean | undefined;
const get: Get = ($?: ReadableLike): unknown => {
const readable = getReadable($);
if (!readable) return $;
self.addDep_(readable as ReadableImpl);
return readable.get();
};
const self = new ReadableImpl(self => {
const isFirst = !running;
running = true;
if (isFirst && self.deps_?.size) {
for (const dep of self.deps_.keys()) {
self.removeDep_(dep);
}
}
try {
return fn(get);
} finally {
/** c8 ignore else -- @preserve */
if (isFirst) {
running = false;
}
}
}, config);
return self;
};
|