Skip to main content

dedupeByKey()

dedupeByKey<T>(key, fn): Promise<T>

Queues functions by key to prevent duplicate concurrent executions.

๐Ÿ’Ž Why is this a Hidden Gem?

Prevents duplicate concurrent execution. If 5 components invoke an operation with the same key, only 1 is executed and the result is shared.

note

Concurrent calls with the same key share a single execution. Key is released on completion.


Type Parametersโ€‹

T: Tโ€‹

The return type of the function.


Parametersโ€‹

key: stringโ€‹

Unique key for the operation.

fn: () => Promise<T>โ€‹

The async function to execute.


Returns: Promise<T>โ€‹

Promise that resolves to the function result.


Throwsโ€‹

Rejects if the queued function rejects.


Sinceโ€‹

1.1.0


Performanceโ€‹

Uses Map for O(1) key lookup to prevent duplicate concurrent executions.


Also known asโ€‹

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


Exampleโ€‹

// Both return same result, but fetchUser is called once
const user1 = dedupeByKey('user-123', () => fetchUser('123'));
const user2 = dedupeByKey('user-123', () => fetchUser('123'));

// Different keys execute independently
const userA = dedupeByKey('user-A', () => fetchUser('A'));
const userB = dedupeByKey('user-B', () => fetchUser('B'));

How it works?โ€‹

Prevents duplicate concurrent executions for the same key. Multiple calls with identical keys share a single execution โ€” the key is released on completion.

Different Keys Execute Independentlyโ€‹


Use Casesโ€‹

Prevent duplicate API calls ๐Ÿ“Œโ€‹

Queue API calls by key to prevent multiple identical requests from being made simultaneously. Essential for avoiding race conditions and reducing unnecessary network traffic.

// Prevent duplicate user fetches
const getUserData = async (userId: string) => {
return await dedupeByKey(`user-${userId}`, async () => {
const response = await fetch(`/api/users/${userId}`);
return response.json();
});
};

// Multiple calls with same userId will only make one API request
const user1 = await getUserData("123");
const user2 = await getUserData("123");
const user3 = await getUserData("123");
// Only one API call is made, all return the same result

Manage resource loading efficientlyโ€‹

Prevent duplicate resource loading operations to optimize performance. Critical for image loading, heavy computations, or cache warming.

// Prevent duplicate cache operations
const getCachedData = async (cacheKey: string) => {
return await dedupeByKey(`cache-${cacheKey}`, async () => {
let data = await cache.get(cacheKey);
if (!data) {
data = await expensiveOperation();
await cache.set(cacheKey, data);
}
return data;
});
};

Shared initialization across modulesโ€‹

Ensure expensive setup runs only once even when triggered from multiple entry points. Perfect for lazy singletons, connection pools, or SDK initialization.

const getDatabase = () => {
return dedupeByKey("db-connection", async () => {
console.log("Connecting to database...");
const connection = await createConnection(config);
await connection.runMigrations();
return connection;
});
};

// Called from multiple modules simultaneously
const [db1, db2, db3] = await Promise.all([
getDatabase(), // From user-service
getDatabase(), // From order-service
getDatabase(), // From notification-service
]);

// "Connecting to database..." logged only once
// db1 === db2 === db3 (same instance)