@avatijs/memoize
v0.1.2
Published
Memoize package part of Avati project
Downloads
147
Maintainers
Readme
Memoize Function Utility
A robust and efficient TypeScript utility for memoizing functions with support for:
- Cache Size Limits: Control the maximum number of cached entries.
- Time-to-Live (TTL): Set expiration time for cached entries.
- LRU Cache Eviction: Automatically evict least recently used items when the cache limit is reached.
- Complex Argument Handling: Safely memoize functions with complex arguments, including objects with circular references.
Table of Contents
Installation
You can install this utility via npm:
npm install @avatijs/memoize
Usage
Import the memoize
function into your project:
import { memoize } from '@avatijs/memoize';
Basic Memoization
Memoize a simple function to cache its results:
function add(a: number, b: number): number {
console.log('Computing...');
return a + b;
}
const memoizedAdd = memoize(add);
console.log(memoizedAdd(1, 2)); // Outputs: Computing... 3
console.log(memoizedAdd(1, 2)); // Outputs: 3 (cached result)
Cache Size Limit
Limit the cache size using the maxCacheSize
option:
const memoizedAddLimited = memoize(add, { maxCacheSize: 2 });
memoizedAddLimited(1, 2); // Cached
memoizedAddLimited(2, 3); // Cached
memoizedAddLimited(3, 4); // Cached, cache size exceeds limit, least recently used item is evicted
Time-to-Live (TTL)
Set a TTL (in milliseconds) after which cached entries expire:
const memoizedAddWithTTL = memoize(add, { ttl: 5000 }); // Entries expire after 5 seconds
memoizedAddWithTTL(1, 2); // Cached
setTimeout(() => {
memoizedAddWithTTL(1, 2); // Recomputed after TTL expires
}, 6000);
Handling Complex Arguments
Memoize functions that accept complex arguments, including objects and arrays:
function processData(data: { id: number; value: string }): string {
console.log('Processing data...');
return `ID: ${data.id}, Value: ${data.value}`;
}
const memoizedProcessData = memoize(processData);
const data = { id: 1, value: 'Test' };
memoizedProcessData(data); // Outputs: Processing data... 'ID: 1, Value: Test'
memoizedProcessData(data); // Cached result
Preserving this
Context
Memoize methods that rely on the this
context:
class Multiplier {
factor = 2;
multiply = memoize(function (this: Multiplier, x: number) {
return x * this.factor;
});
}
const multiplier = new Multiplier();
console.log(multiplier.multiply(5)); // Outputs: 10
Memoizing Asynchronous Functions
Memoize functions that return promises:
async function fetchData(url: string): Promise<string> {
const response = await fetch(url);
return response.text();
}
const memoizedFetchData = memoize(fetchData);
memoizedFetchData('https://api.example.com/data').then(console.log);
API
memoize
Creates a memoized version of a function with optional cache size limit and TTL.
Signature
function memoize<Args extends any[], Return>(
fn: (...args: Args) => Return,
options?: MemoizeOptions
): (...args: Args) => Return;
Parameters
fn
: The function to memoize.options
(optional): An object specifying memoization options.
MemoizeOptions
An interface defining the memoization options.
Properties
maxCacheSize
(optional):number
- Maximum number of entries to store in the cache.
- Default:
Infinity
ttl
(optional):number
- Time-to-live in milliseconds for cached entries.
- Entries expire after
ttl
milliseconds. - Default:
undefined
(no expiration)
Implementation Details
LRU Cache
An internal Least Recently Used (LRU) cache is used to manage cached entries efficiently. When the cache size exceeds maxCacheSize
, the least recently used item is evicted.
Key Generation
A robust key generation function handles complex arguments, including:
- Primitives: Compared by value.
- Objects: Compared by identity using a unique ID assigned via a
WeakMap
. - Functions: Stringified to include their code in the key.
- Circular References: Safely handled without causing errors.
Testing
Extensive test cases have been written using Jest to ensure reliability.
Running Tests
Run the tests:
npx jest
Test Cases Covered
- Caching Basic Function Calls
- Handling Different Arguments
- Max Cache Size Limit
- Time-to-Live (TTL) Expiration
- Complex Arguments and Circular References
- Functions with Side Effects
- Preservation of
this
Context - Asynchronous Functions
- Exception Handling
- Non-Serializable Arguments
- Zero TTL (No Caching)
- Multiple Memoized Functions
Changelog
Please see CHANGELOG for more information what has changed recently.
Contributing
I welcome contributions from developers of all experience levels. If you have an idea, found a bug, or want to improve something, I encourage you to get involved!
How to Contribute
- Read Contributing Guide for details on how to get started.
- Fork the repository and make your changes.
- Submit a pull request, and we’ll review it as soon as possible.
License
Avati is open-source and distributed under the MIT License.