Skip to content

JS kata bank

Small JavaScript utilities to write from scratch: debounce, throttle, Promise.all, a promise pool, retry, an event emitter, memoize, deep clone, an LRU cache and more.

19 lessons

Timing and async control

  1. 1Kata: debounceWrite the state, not just the timer: every exit (fire, cancel, flush) leaves timer null and nothing saved.
  2. 2Kata: throttle (leading + trailing)The window is a timer, not a timestamp: only a timer can run the last call, and that run opens the next window.
  3. 3Kata: Promise.allAdopt each item, write by index, count down to zero, settle an empty input at once, and let the first rejection reject.
  4. 4Kata: Promise.allSettledTwo handlers in one then on every input, an entry with a status from each, and Promise.all over the lot.
  5. 5Kata: promise pool (concurrency limit)Functions in, a checked limit, claim with next++ before the await, write by index, and stop claiming at the first failure.
  6. 6Kata: retry with exponential backoff and jitterA retry kata is judged at its edges: how many calls, where the waits fall, which error escapes, and whether tests can fake time.
  7. 7Kata: cancellable fetch with AbortControllerA timeout is a timer you own: start it before the request, keep it over the body, and clear it on every way out.

Events and state (observer family)

  1. 8Kata: event emitter (on, off, once, emit)Remove by identity, exactly once: the wrapper removes itself, an unsubscribe removes its own registration, and no array emit holds is edited.
  2. 9Kata: onceKeep the flag apart from the result, and raise it only when fn has returned.
  3. 10Kata: tiny reactive store (subscribe + select)Replace the snapshot, never edit it: compare before you build, swap before you call, and let select remember the slice it last reported.

Functions

  1. 11Kata: memoizeKey on the exact arguments, store exactly what came back, and give back nothing that failed.
  2. 12Kata: curryNever keep the arguments in one place: every call gets a new array, and every partial owns its own.
  3. 13Kata: pipe, compose and pipeAsyncRun the list in order, give the first function every argument, and decide what an empty list returns before you write a loop.

Data and objects

  1. 14Kata: deep cloneRegister the copy before you recurse: one seen-map per call closes cycles and keeps shared objects shared.
  2. 15Kata: deepEqualSame type, same key set, equal values: count the keys, check each is b's own, then recurse.
  3. 16Kata: get by pathGuard each read with == null; give the fallback only for undefined.
  4. 17Kata: flatten with depthOpen arrays only, count depth down per level, write to a new list, and keep your own stack when nesting runs deep.
  5. 18Kata: groupByGroup into an object with no prototype; a {} already answers to names you never stored.
  6. 19Kata: LRU cacheThe Map's order is the recency list: every hit and every put moves its key to the end, and eviction takes the first key.