fn-merge-cache
Version:
`FnMergeCache` is a caching utility that allows functions to cache their results based on input arguments, with options for cache lifetime, size limits, error handling, and parameter comparison, while supporting cache invalidation via tags and global reva
207 lines (153 loc) • 6.49 kB
Markdown
# fn-merge-cache
`FnMergeCache` is a caching utility that allows functions to cache their results based on input arguments, with options for cache lifetime, size limits, error handling, and parameter comparison, while supporting cache invalidation via tags and global revalidation.
[](https://npmjs.com/package/fn-merge-cache)
[](https://npmjs.com/package/fn-merge-cache)
[中文文档](https://github.com/hurryhuang1007/fn-merge-cache/blob/main/README.zh.md)
## Install
```bash
npm install fn-merge-cache
```
## Features
1. Cache function: supports caching the return results of functions to improve performance and reduce repeated calculations.
2. Cache expiration: supports setting the expiration time (TTL) of the cache, and automatically clears the cache after the time expires.
3. Cache size limit: supports setting the maximum cache size to limit the size of the cache pool.
4. Error handling: you can choose whether to cache the error result when the function call fails.
5. Parameter comparison: allows custom parameter comparison functions to determine whether the cached results can be used.
6. Cache invalidation: cache invalidation and revalidation (revalidation) through the tag mechanism, you can revalidate the cache by tag or globally.
7. Merge promises: support processing the returned Promise, and update the cache status after the Promise is resolved.
8. Event-driven: use EventEmitter for cache invalidation notification, allowing fine control over the validity of the cache.
9. Intelligent caching strategy: When the cache TTL is not set, the LRU algorithm will be used.
## API
### FnMergeCache
A tool for caching function call results, supporting cache expiration, size limits, error handling, tag mechanisms, and more.
#### Constructor
```typescript
new FnMergeCache<A extends any[], R>(
fn: (...args: A) => R,
opt?: {
cache?: boolean;
cacheOnError?: boolean;
argComparer?: (a: A, b: A) => boolean;
ttl?: number;
maxCacheSize?: number;
tags?: string[];
}
)
```
#### Parameters
- fn: The function to be cached.
- cache: Whether to enable caching. Default is true.
- cacheOnError: Whether to cache the result even if the function throws an error. Default is false.
- argComparer: A custom function to compare function arguments. Defaults to lodash's isEqual.
- ttl: The cache time-to-live (in milliseconds), 0 means never expires. Default is 0.
- maxCacheSize: The maximum number of cached items, 0 means no limit. Default is 0.
- tags: Tags for cache invalidation.
#### Methods
- `call(...args: A): R`
Calls the cached function with the provided arguments args, returning the result. If a valid cached result exists, it returns the cached result; otherwise, it executes the function and caches the result.
- `revalidate()`
Clears all cached data. This method clears all cache data related to the instance.
- `dispose()`
Releases the cache instance resources, stops caching, and removes all event listeners.
### createMergedCachedFn
Creates a function with caching functionality.
```typescript
function createMergedCachedFn<A extends any[], R>(
fn: (...args: A) => R,
opt?: {
cache?: boolean;
cacheOnError?: boolean;
argComparer?: (a: A, b: A) => boolean;
ttl?: number;
maxCacheSize?: number;
tags?: string[];
}
): (...args: A) => R
```
#### Parameters
- fn: The function to be cached.
- opt: Cache options, same as the options for FnMergeCache constructor.
#### Returns
A function with caching functionality, behaving the same as FnMergeCache.
### revalidateTag
Revalidate the cache by tag(s) or globally.
```typescript
function revalidateTag(tags?: string | string[]): void
```
## Basic Usage
```javascript
import { FnMergeCache, revalidateTag } from 'fn-merge-cache';
// define a function that needs to be cached
function fetchData(id) {
console.log(`Fetching data for ${id}`);
return new Promise((resolve) => {
setTimeout(() => resolve(`Data for ${id}`), 1000);
});
}
// create a cache instance
const cache = new FnMergeCache(fetchData, {
cache: true, // enable cache
cacheOnError: true, // cache error results
ttl: 5000, // cache expiration time
maxCacheSize: 10, // maximum cache size
tags: ['data-fetch'], // cache tags
});
// call the function with the same parameter
cache.call(1).then((data) => {
console.log(data); // Output: Fetching data for 1 \n Data for 1
});
cache.call(1).then((data) => {
console.log(data); // Output: Data for 1 (from cache)
});
// call the function with different parameters
cache.call(2).then((data) => {
console.log(data); // Output: Fetching data for 2 \n Data for 2
});
// revalidate the cache
cache.revalidate();
// or revalidate the cache by tag(s)
revalidateTag('data-fetch');
// or revalidate all caches
revalidateTag();
// call the function with the same parameter
cache.call(1).then((data) => {
console.log(data); // Output: Fetching data for 1 \n Data for 1 (fetch again)
});
// dispose the cache instance
cache.dispose();
```
### if a cache instance DO NOT need to be disposed, you can use the createMergedCachedFn function
```javascript
import { createMergedCachedFn, revalidateTag } from 'fn-merge-cache';
const mergedCachedFn = createMergedCachedFn(fetchData, {
cache: true,
cacheOnError: true,
ttl: 5000,
maxCacheSize: 10,
tags: ['data-fetch'],
});
// call the function with the same parameter
mergedCachedFn(1).then((data) => {
console.log(data); // Output: Fetching data for 1 \n Data for 1
});
// revalidate the cache
revalidateTag('data-fetch');
```
## Merge Usage (only when the fn returns a Promise (async function))
```javascript
import { createMergedCachedFn } from 'fn-merge-cache';
const justMergeFn = createMergedCachedFn(fetchData, {
cache: false,
});
justMergeFn(1).then((data) => {
console.log(data); // Output: Fetching data for 1 \n Data for 1
});
justMergeFn(1).then((data) => {
console.log(data); // Output: Data for 1 (merged call)
justMergeFn(1).then((data) => {
console.log(data); // Output: Fetching data for 1 \n Data for 1 (fetch again)
});
});
```
## LICENSE
MIT