72 lines
1.7 KiB
JavaScript
72 lines
1.7 KiB
JavaScript
import { reactive } from 'vue'
|
|
|
|
/**
|
|
* Vue 3 composable for memoizing functions.
|
|
* Works across components and SPA navigation (module-level singleton cache).
|
|
*
|
|
* Usage:
|
|
* const { memoize, memoizeFull } = useMemoize()
|
|
* const add10 = (n) => n + 10
|
|
* const cachedAdd = memoize(add10)
|
|
* cachedAdd(5) // calculates
|
|
* cachedAdd(5) // returns cached result
|
|
*/
|
|
export function useMemoize() {
|
|
// reactive singleton caches
|
|
const cacheSingle = reactive({})
|
|
const cacheMulti = reactive({})
|
|
|
|
/**
|
|
* Memoize a single-argument function.
|
|
* @param {Function} fn - Function with one argument
|
|
* @returns {Function} Memoized function
|
|
*/
|
|
function memoize(fn) {
|
|
return (arg) => {
|
|
if (arg in cacheSingle) {
|
|
// console.log('Fetching from cache')
|
|
return cacheSingle[arg]
|
|
}
|
|
// console.log('Calculating result')
|
|
const result = fn(arg)
|
|
cacheSingle[arg] = result
|
|
return result
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Memoize a function with multiple arguments.
|
|
* @param {Function} fn - Function with any number of arguments
|
|
* @returns {Function} Memoized function
|
|
*/
|
|
function memoizeFull(fn) {
|
|
return (...args) => {
|
|
const key = JSON.stringify(args)
|
|
if (cacheMulti[key]) {
|
|
// console.log('Fetching from cache for:', args)
|
|
return cacheMulti[key]
|
|
}
|
|
|
|
const result = fn(...args)
|
|
cacheMulti[key] = result
|
|
return result
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Optional: clear caches
|
|
*/
|
|
function clearCache() {
|
|
Object.keys(cacheSingle).forEach(k => delete cacheSingle[k])
|
|
Object.keys(cacheMulti).forEach(k => delete cacheMulti[k])
|
|
}
|
|
|
|
return {
|
|
memoize,
|
|
memoizeFull,
|
|
cacheSingle,
|
|
cacheMulti,
|
|
clearCache
|
|
}
|
|
}
|