once
The once utility restricts a function so that it can only be executed a single time. Subsequent calls to the restricted function will return the result of the first invocation. It also includes a reset method to allow the function to be run again if needed.
Implementation
View Source Code
ts
import type { Fn } from '../types';
/**
* Create a function that runs once and returns the first result.
*
* @example
* ```ts
* const onceRandom = once(() => Math.random())
* onceRandom() // 0.3
* onceRandom() // 0.3
*
* onceRandom.reset()
*
* onceRandom() // 0.2
* onceRandom() // 0.2
* ```
*
* @param fn - The function to wrap.
*
* @returns A function that can only be called once.
*/
export const once = <T extends Fn>(fn: T): T & { reset: () => void } => {
let result: ReturnType<T> | undefined;
let called = false;
const wrappedFn = ((...args: Parameters<T>): ReturnType<T> => {
if (!called) {
result = fn(...args);
called = true;
}
return result as ReturnType<T>;
}) as T & { reset: () => void };
wrappedFn.reset = () => {
result = undefined;
called = false;
};
return wrappedFn;
};Features
- Isomorphic: Works in both Browser and Node.js.
- Stateful: Remembers the result of the first call.
- Resettable: Manual control to clear the cached result and allow a new execution.
- Type-safe: Preserves the argument and return types of the original function.
API
ts
function once<T extends (...args: any[]) => any>(fn: T): T;Parameters
fn: The function to restrict.
Returns
- A new function that only executes
fnonce. - The returned function has a
.reset()property to clear its state.
Examples
One-time Initialization
ts
import { once } from '@vielzeug/toolkit';
const initializeApp = once(() => {
console.log('Connecting to database...');
return { status: 'ready' };
});
initializeApp(); // Logs message, returns { status: 'ready' }
initializeApp(); // Returns same object, no logResettable Logic
ts
import { once } from '@vielzeug/toolkit';
const getData = once(() => fetch('/api/data'));
await getData(); // Performs fetch
await getData(); // Returns cached promise
// Force a new fetch later
getData.reset();
await getData(); // Performs new fetchImplementation Notes
- Performance-optimized using a simple closure.
- The
.reset()method is ideal for handling logout/re-login scenarios or refreshing stale caches. - Throws
TypeErroriffnis not a function.