Skip to main content

before()

before<Args, Return>(func, n): (...args) => Return | undefined

Creates a function that invokes func at most n-1 times. Subsequent calls return the result of the last invocation.

note

When n โ‰ค 1, func is never invoked and undefined is always returned.


Type Parametersโ€‹

Args: Args extends unknown[]โ€‹

The argument types of the function.

Return: Returnโ€‹

The return type of the function.


Parametersโ€‹

func: (...args) => Returnโ€‹

The function to restrict.

n: numberโ€‹

The number of calls at which func is no longer invoked.


Returnsโ€‹

The new restricted function. Returns undefined until func is first invoked.


Throwsโ€‹

RangeError If n is negative or not an integer.


See Alsoโ€‹

after - Inverse operation: invokes func only after n calls.


Sinceโ€‹

2.0.0


Also known asโ€‹

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


Exampleโ€‹

let count = 0;
const increment = before(() => ++count, 3);

increment(); // => 1
increment(); // => 2
increment(); // => 2 (no longer invoked)
increment(); // => 2

// Use case: Initialize only once
const initialize = before(() => {
console.log('Initializing...');
return { ready: true };
}, 2);

initialize(); // "Initializing..." => { ready: true }
initialize(); // => { ready: true } (cached)

How it works?โ€‹

Creates a function that invokes at most n-1 times. After n-1 invocations, subsequent calls return the last result.

before vs afterโ€‹

before(fn, 3)after(fn, 3)
Call 1checkmark executescross skips
Call 2checkmark executescross skips
Call 3+padlock cachedcheckmark executes

Use Casesโ€‹

Limited Retries for operations ๐Ÿ“Œโ€‹

Limit the number of retry attempts for operations. Essential for resilient error handling.

import { before } from "pithos/arkhe/function/before";

const attemptConnection = async () => {
const response = await fetch("/api/health");
if (!response.ok) throw new Error("Connection failed");
return response.json();
};

// Allow only 3 attempts (calls on 1st, 2nd, 3rd - returns last result after)
const limitedRetry = before(attemptConnection, 4);

async function connectWithRetry() {
for (let i = 0; i < 5; i++) {
try {
const result = await limitedRetry();
if (result) return result;
} catch (e) {
console.log(`Attempt ${i + 1} failed`);
}
}
throw new Error("All retries exhausted");
}

One-time Initialization ๐Ÿ“Œโ€‹

Ensure initialization code runs only once. Critical for singleton patterns and setup.

import { before } from "pithos/arkhe/function/before";

const initializeApp = () => {
console.log("Initializing application...");
// Heavy setup: load config, connect to DB, etc.
return { initialized: true, timestamp: Date.now() };
};

// Only actually initialize on first call
const safeInit = before(initializeApp, 2);

// First call initializes
const result1 = safeInit(); // Logs "Initializing application..."
console.log(result1); // { initialized: true, timestamp: ... }

// Subsequent calls return the cached result
const result2 = safeInit(); // No log, returns same result
console.log(result1 === result2); // true (same reference)

Rate Limited Actions for user interactionsโ€‹

Limit how many times a user action can trigger. Important for preventing spam clicks.

import { before } from "pithos/arkhe/function/before";

const submitForm = (data: FormData) => {
console.log("Submitting form...");
return fetch("/api/submit", { method: "POST", body: data });
};

// Allow only 1 submission (before 2nd call)
const limitedSubmit = before(submitForm, 2);

// In form handler
form.addEventListener("submit", async (e) => {
e.preventDefault();
const data = new FormData(form);

// Only first click actually submits
const result = await limitedSubmit(data);
if (result) {
console.log("Form submitted successfully");
} else {
console.log("Form already submitted");
}
});