Skip to main content

once()

once<Args, Result>(fn): (...args) => Result

Creates a function that can only be called once.

note

Subsequent calls return the cached result and ignore new arguments.


Type Parametersโ€‹

Args: Args extends unknown[]โ€‹

The argument types of the function.

Result: Resultโ€‹

The return type of the function.


Parametersโ€‹

fn: (...args) => Resultโ€‹

The function to restrict to one execution.


Returnsโ€‹

The restricted function that caches the first call's result.


Sinceโ€‹

2.0.0


Performanceโ€‹

O(1) lookup after first call. Single boolean flag check for optimal performance.


Also known asโ€‹

once (Lodash, es-toolkit, Remeda, Radashi, Ramda) ยท โŒ (Effect, Modern Dash, Antfu)


Exampleโ€‹

// Basic usage
const initialize = once(() => {
console.log('Initializing...');
return 'initialized';
});

initialize(); // "Initializing..." -> "initialized"
initialize(); // "initialized" (cached)

// With parameters (ignores new args after first call)
const createUser = once((name: string) => ({ id: 1, name }));

createUser('John'); // { id: 1, name: 'John' }
createUser('Jane'); // { id: 1, name: 'John' } (cached)

// Async functions
const fetchData = once(async () => fetch('/api/data'));
await fetchData(); // Fetches
await fetchData(); // Cached promise

How it works?โ€‹

Creates a function that executes only once โ€” subsequent calls return the cached result.

Simple Flowโ€‹

Key Behaviorโ€‹

New arguments are ignored after the first call:


Use Casesโ€‹

Initialize resources only once ๐Ÿ“Œโ€‹

Ensure initialization code runs only once to prevent duplicate setup. Essential for resource management and preventing initialization errors.

const initApp = once(() => {
console.log("App initialized");
// ... setup code
});

initApp(); // "App initialized"
initApp(); // (ignored)

Create singletons safelyโ€‹

Ensure singleton instances are created only once. Essential for state management and ensuring single instance patterns.

const getDb = once(() => new DatabaseConnection());
const db1 = getDb();
const db2 = getDb();

console.log(db1 === db2); // true

Lazy-initialize an SDK or API clientโ€‹

Initialize a third-party SDK on first use instead of at app startup. The standard pattern for Stripe, Firebase, Analytics, or any heavy client library.

const getStripe = once(() => {
return loadStripe(process.env.STRIPE_PUBLIC_KEY);
});

const getAnalytics = once(() => {
return initializeAnalytics({ trackingId: "UA-XXXXX" });
});

// Called from multiple components โ€” SDK loads only on first call
async function handleCheckout() {
const stripe = await getStripe();
stripe.redirectToCheckout({ sessionId });
}