once
EditInvokes a function once and reuses its return value or thrown error.
type OnceState<Return> = | { status: "idle" } | { status: "running" } | { status: "returned"; value: Return } | { status: "threw"; error: unknown };
export type OnceFunction< Arguments extends unknown[], Return, This = unknown,> = (this: This, ...args: Arguments) => Return;
type AnyFunction = (this: never, ...args: never[]) => unknown;
/** Invokes a function once, then reuses its return value or thrown error. */export const once = <Function extends AnyFunction>( fn: Function): OnceFunction< Parameters<Function>, ReturnType<Function>, ThisParameterType<Function>> => { let state: OnceState<ReturnType<Function>> = { status: "idle" };
const wrapped = function ( this: ThisParameterType<Function>, ...args: Parameters<Function> ): ReturnType<Function> { if (state.status === "returned") return state.value; if (state.status === "threw") throw state.error; if (state.status === "running") { throw new Error("once callback cannot invoke itself recursively"); }
state = { status: "running" }; try { const value = Reflect.apply(fn, this, args) as ReturnType<Function>; state = { status: "returned", value }; return value; } catch (error) { state = { status: "threw", error }; throw error; } };
return wrapped;};Download
Section titled “Download”wget -O src/lib/once.ts https://raw.githubusercontent.com/jrTilak/lazykit/HEAD/registry/functions/once.tstemp_dir="$(mktemp -d)" && bunx degit jrTilak/lazykit/registry/functions "$temp_dir" && mv "$temp_dir/once.ts" src/lib/once.ts && rm -r "$temp_dir"Examples
Section titled “Examples”import { once } from "./once";
// Function that we want to run only onceconst initialize = () => console.log("Initialization completed!");
const initializeOnce = once(initialize);
// Call the function multiple timesinitializeOnce(); // Output: Initialization completed!initializeOnce(); // No outputinitializeOnce(); // No outputfn((...args: A) => R) — Function invoked with the arguments and receiver from the first call.
Returns
Section titled “Returns”(...args: A) => R — A wrapper that returns the first result on later calls. If the first invocation throws, later calls rethrow the same value.