UNPKG

@tienedev/datype

Version:

Modern TypeScript utility library with pragmatic typing and zero dependencies

99 lines (96 loc) 2.71 kB
'use strict'; /** * Creates a function that can only be called once. Subsequent calls return the result of the first call. * * @param fn - The function to restrict to one execution * @returns A new function that can only be called once * * @example * ```typescript * import { once } from 'datype'; * * // Basic usage * const sayHello = once(() => { * console.log('Hello!'); * return 'greeting'; * }); * * sayHello(); // logs "Hello!" and returns "greeting" * sayHello(); // returns "greeting" without logging * sayHello(); // returns "greeting" without logging * * // With parameters * const addOnce = once((a: number, b: number) => { * console.log(`Adding ${a} + ${b}`); * return a + b; * }); * * addOnce(2, 3); // logs "Adding 2 + 3" and returns 5 * addOnce(4, 5); // returns 5 without logging (ignores new arguments) * * // Expensive computation * const expensiveCalculation = once(() => { * console.log('Performing expensive calculation...'); * // Simulate expensive work * let result = 0; * for (let i = 0; i < 1000000; i++) { * result += Math.random(); * } * return result; * }); * * const result1 = expensiveCalculation(); // Does the calculation * const result2 = expensiveCalculation(); // Returns cached result * console.log(result1 === result2); // true * * // Event handler that should only run once * const handleFirstClick = once((event: Event) => { * console.log('First click detected!'); * // Remove event listener or show modal, etc. * }); * * button.addEventListener('click', handleFirstClick); * * // Initialization function * const initialize = once(() => { * console.log('Initializing application...'); * // Setup code that should only run once * return { initialized: true }; * }); * * // Real-world example: lazy loading * const loadConfig = once(async () => { * console.log('Loading configuration...'); * const response = await fetch('/api/config'); * return response.json(); * }); * * // Multiple calls will return the same Promise * const config1 = await loadConfig(); // Makes API call * const config2 = await loadConfig(); // Returns same Promise result * ``` */ function once(fn) { let called = false; let result; let hasError = false; let error; return function onceFn(...args) { if (!called) { called = true; try { result = fn(...args); } catch (err) { hasError = true; error = err; throw err; } } if (hasError) { throw error; } return result; }; } exports.once = once;