Memo
15 exports from @ontologyio/receta/memo.
Everything exported from @ontologyio/receta/memo. New here? Start with the Memo guide.
Functions
clearCache
Clears the cache of a memoized function.
function clearCache<Args extends readonly unknown[], R>(memoized: MemoizedFunction<Args, R> | MemoizedAsyncFunction<Args, R>): voidimport { memoize, clearCache } from '@ontologyio/receta/memo'
const expensive = memoize((n: number) => fibonacci(n))
expensive(40) // computed
expensive(40) // cached
clearCache(expensive)
expensive(40) // computed again
// Alternative: use .clear() method
expensive.clear()invalidateAll
Clears the cache of multiple memoized functions at once.
Useful for coordinated invalidation across related caches.
function invalidateAll(...memoized: AnyMemoized[]): voidimport { memoize, memoizeAsync, invalidateAll } from '@ontologyio/receta/memo'
const getUser = memoize(fetchUser)
const getUserPosts = memoizeAsync(fetchUserPosts)
const getUserComments = memoizeAsync(fetchUserComments)
// After user deletion
async function deleteUser(id: string) {
await db.users.delete(id)
// Clear all user-related caches
invalidateAll(getUser, getUserPosts, getUserComments)
}
// Alternative: clear specific entries before clearing all
getUser.cache.delete(id)
getUserPosts.cache.delete(id)
invalidateAll(getUserComments) // Clear everything from this oneinvalidateMany
Invalidates multiple cache entries by their keys.
Useful when you know specific keys to invalidate after a batch operation.
function invalidateMany<K>(memoized: AnyMemoized, keys: K[]): voidimport { memoize, invalidateMany } from '@ontologyio/receta/memo'
const getUser = memoize(fetchUser)
// After batch user update
await updateUsers(['1', '2', '3'], newData)
invalidateMany(getUser, ['1', '2', '3'])
// Next calls will recompute
getUser('1') // Fetched again
getUser('2') // Fetched againinvalidateWhere
Invalidates cache entries matching a predicate.
Useful for conditional invalidation based on key patterns or cached values.
Works with the default cache, ttlCache, lruCache and custom caches that have a
forEach method. Throws for weakCache, because a WeakMap can't be listed.
function invalidateWhere<K = unknown, V = unknown>(memoized: AnyMemoized, predicate: (key: K, value?: V | undefined) => boolean): voidimport { memoizeBy, invalidateWhere } from '@ontologyio/receta/memo'
const getUser = memoizeBy(
fetchUser,
(id, type) => `${type}:${id}`
)
// Invalidate all admin users
invalidateWhere<string>(getUser, (key) => key.startsWith('admin:'))
// Invalidate by value condition
invalidateWhere<string, User>(getUser, (_key, user) => user?.deleted === true)lruCache
Creates a Least-Recently-Used (LRU) cache with a maximum size.
When the cache reaches max size, the least recently accessed entry is evicted. Useful for limiting memory usage while keeping hot data cached.
function lruCache<K, V>(maxSize: number): Cache<K, V>import { memoize, lruCache } from '@ontologyio/receta/memo'
// Cache up to 100 users
const getUser = memoize(fetchUser, {
cache: lruCache(100)
})
// After 100 different users:
getUser('user-001') // cached
getUser('user-002') // cached
// ... 100 more calls ...
getUser('user-101') // causes 'user-001' to be evictedmemoize
Creates a memoized version of a function that caches results based on arguments.
By default, uses a simple Map cache with the first argument as the key.
For multi-argument functions or complex keys, use memoizeBy() instead.
function memoize<Args extends readonly [unknown, ...unknown[]], R>(fn: (...args: Args) => R, options?: MemoizeOptions<string>): MemoizedFunction<Args, R>// Basic memoization
const fibonacci = (n: number): number => {
if (n <= 1) return n
return fibonacci(n - 1) + fibonacci(n - 2)
}
const memoFib = memoize(fibonacci)
memoFib(40) // computed (takes time)
memoFib(40) // cached (instant)
// With max size
const getUser = memoize(fetchUser, { maxSize: 100 })
// With TTL
const getWeather = memoize(fetchWeather, { cache: ttlCache(5 * 60 * 1000) }) // 5 minSee also memoizeBy, memoizeAsync.
memoizeAsync
Creates a memoized async function with request deduplication.
Key features:
- Caches resolved promises
- Prevents duplicate in-flight requests (thundering herd protection)
- Failed promises are not cached
- Supports TTL and LRU cache strategies
function memoizeAsync<Args extends readonly unknown[], R>(fn: (...args: Args) => Promise<R>, options?: MemoizeOptions<string> & { keyFn?: KeyFn<Args, unknown> | undefined; }): MemoizedAsyncFunction<Args, R>// Basic async memoization
const fetchUser = memoizeAsync(async (id: string) => {
const res = await fetch(`/api/users/${id}`)
return res.json()
})
// Concurrent calls - only 1 fetch happens
const [a, b, c] = await Promise.all([
fetchUser('123'),
fetchUser('123'),
fetchUser('123')
]) // All return same result from single API call
// With TTL
const getWeather = memoizeAsync(
async (city: string) => api.fetchWeather(city),
{ cache: ttlCache(5 * 60 * 1000) } // 5 min cache
)
// Custom key extraction
const fetchData = memoizeAsync(
async (opts: { id: string; type: string }) => api.fetch(opts),
{ keyFn: (opts) => `${opts.id}:${opts.type}` }
)See also memoize, memoizeBy.
memoizeBy
Creates a memoized function with custom key extraction.
Use this when:
- Function takes multiple arguments
- Function takes complex objects as arguments
- You need custom cache key logic
function memoizeBy<Args extends readonly unknown[], R, K>(fn: (...args: Args) => R, keyFn: KeyFn<Args, K>, options?: MemoizeOptions<K>): MemoizedFunction<Args, R>// Multi-argument function
const add = (a: number, b: number) => a + b
const memoAdd = memoizeBy(add, (a, b) => `${a},${b}`)
memoAdd(2, 3) // computed
memoAdd(2, 3) // cached
// Complex object arguments
interface FetchOptions {
id: string
include?: string[]
}
const fetchUser = memoizeBy(
(opts: FetchOptions) => api.fetch(opts),
(opts) => JSON.stringify(opts)
)
// Object key (use with WeakMap cache)
const processNode = memoizeBy(
(node: Node) => expensiveOperation(node),
(node) => node // object as key
)See also memoize, memoizeAsync.
ttlCache
Creates a time-to-live (TTL) cache that automatically expires entries.
Entries are removed after the specified TTL duration. Useful for caching data that becomes stale (API responses, weather, prices, etc.).
function ttlCache<K, V>(ttlMs: number): Cache<K, V>import { memoize, ttlCache } from '@ontologyio/receta/memo'
// Cache weather data for 5 minutes
const getWeather = memoize(fetchWeather, {
cache: ttlCache(5 * 60 * 1000)
})
getWeather('NYC') // fetches from API
getWeather('NYC') // cached
// ... 5 minutes later ...
getWeather('NYC') // fetches from API againweakCache
Creates a WeakMap-based cache for object keys.
Advantages:
- Entries are garbage collected when keys are no longer referenced
- No memory leaks from unreferenced objects
- Perfect for caching computations on DOM nodes, objects, etc.
Limitations:
- Only works with object keys (not primitives)
- Cannot iterate entries
- No size limit or TTL support
function weakCache<K extends object, V>(): Cache<K, V>import { memoizeBy, weakCache } from '@ontologyio/receta/memo'
interface Node {
id: string
children: Node[]
}
const processNode = memoizeBy(
(node: Node) => expensiveOperation(node),
(node) => node, // object as key
{ cache: weakCache() }
)
const node = { id: 'root', children: [] }
processNode(node) // computed
processNode(node) // cached
// When 'node' is GC'd, cache entry is automatically removedTypes
Cache
Cache interface that memoization functions can use. Allows custom cache implementations (Map, LRU, TTL, WeakMap, etc.).
interface Cache<K, V> {
get(key: K): Option<V>
set(key: K, value: V): void
has(key: K): boolean
delete(key: K): boolean
clear(): void
forEach?(callback: (value: V, key: K) => void): void
}KeyFn
Function that extracts a cache key from function arguments.
type KeyFn<Args extends readonly unknown[], K> = (...args: Args) => KMemoizedAsyncFunction
A memoized async function with cache access and deduplication.
interface MemoizedAsyncFunction<Args extends readonly unknown[], R> {
(...args: Args): Promise<R>
cache: Cache<unknown, Promise<R>>
clear: () => void
}MemoizedFunction
A memoized function with cache access.
interface MemoizedFunction<Args extends readonly unknown[], R> {
(...args: Args): R
cache: Cache<unknown, R>
clear: () => void
}MemoizeOptions
Options for memoization functions.
interface MemoizeOptions<K = string> {
cache?: Cache<K, unknown>
maxSize?: number
ttl?: number
}