AniUI Academy

Collapse duplicate in-flight requests

mediumAsync & Promises+250 XPPractice

Independent components requesting the same resource on mount is normal, and firing five identical requests is wasteful. The fix is to remember the promise that is already in flight and hand the same one to every later caller until it settles.

Implement singleFlight(fn). It returns a wrapped function whose **first argument is the key**. When called with a key that has a call in flight, return the exact same promise object without calling fn again. Otherwise call fn with all the arguments it was given and remember the resulting promise under that key. Once that promise settles — whether it fulfils or rejects — remove the entry, so the next call starts fresh work. A rejection is shared by every caller waiting on it.

Arguments

fn(key: any, ...args: any[]) => Promise
The underlying loader. Its first argument is the deduplication key.

Returns

Function — A wrapper that returns the same in-flight promise for concurrent calls with the same key, then releases the slot once that promise settles.

Examples

let calls = 0;
const load = singleFlight(async (key) => {
  calls++;
  await new Promise((r) => setTimeout(r, 20));
  return "value:" + key;
});

const [a, b] = await Promise.all([load("user"), load("user")]);
// a === "value:user", b === "value:user", calls === 1

Collapses concurrent duplicate loads to a single call.

const load = singleFlight(async (key) => key);
const first = load("x");
const second = load("x");
console.log(first === second); // true — identical promise object

Not just equivalent, the exact same promise reference.

What it has to do

  • Return the identical promise object for concurrent calls with the same key.
  • Call fn only once per set of concurrent calls with the same key.
  • Treat different keys as independent.
  • Drop the cached promise once it settles, so a later call re-runs fn.
  • Share rejections with every concurrent caller.

Notes

  • Returning the identical promise object (not just a copy) is what lets === tests pass and matches how libraries like SWR deduplicate.
  • Delete the cache entry inside both the fulfil and reject handlers so a failed load doesn't permanently block the key.

Stuck? The javascript course covers everything this challenge needs.

Try it yourself
Loading playground...
5 tests · +250 XP

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.