Async utils
import { debounce, retry, sleep } from '@gg-software/utils';debounce
The call runs only after wait ms of silence — search inputs, resize handlers. The
returned function carries .cancel() (drop pending) and .flush() (run pending now).
const search = debounce((q: string) => fetchResults(q), 300);
input.addEventListener('input', (e) => search(e.target.value));
search.cancel(); // e.g. on unmount
search.flush(); // e.g. on submitthrottle
Runs at most once per wait ms — immediately on the first call (leading) and once more
with the latest arguments after the window closes (trailing). Scroll/drag handlers.
const onScroll = throttle(() => updatePosition(), 100);
window.addEventListener('scroll', onScroll);sleep
await sleep(500);retry
Retry an async operation with exponential backoff; throws the last error when all attempts fail.
const data = await retry(() => fetchJson(url), {
retries: 4,
delay: 250,
backoff: 2,
onRetry: (error, attempt) => console.warn(`attempt ${attempt} failed`, error),
});Options (RetryOptions):
| Option | Default | Meaning |
|---|---|---|
retries | 3 | total attempts including the first |
delay | 300 | ms before the first retry |
backoff | 2 | delay multiplier after each failure |
onRetry | — | called before each retry (error, attempt) |
memoize
Cache results by argument. Default cache key is JSON.stringify(args) — pass a keyFn
for anything JSON can’t represent. The returned function exposes .cache and .clear().
const slugOf = memoize(slugify);
const priceFor = memoize(computePrice, (item, qty) => `${item.id}:${qty}`);
priceFor.clear();