Description:
Memoizes the promise that being returned by the decorated method.
If the promise would be rejected, the promise won't be memoized.
Another great feature of this decorator is that it delegates requests, for example if the same method has been
called more than one time after the promise was resolved,
only one invocation of the decorated method will be invoked.
Be default the key of the cached value will be the serialized JSON.stringify value of the provided
arguments.
You can supply your own key resolver.
Also, you can provide your own cache, it has to implement the GetterSetter<D> interface, by
default the decorator is using a simple Map<string, Promise<D>>.
For further readying please read this
blog post.
Configuration:
interface MemoizeAsyncConfig<T, D> {
// an optional cache object which should implement the Cache or the AsyncCache interface.
// Internally the decorator is using Map<string, D>
cache?: Cache<D>;
// an optional function (or a function name within the context) that maps the arguments to a specific key.
// The default mapping function is JSON.stringify(args).
keyResolver?: string | (...args: any[]) => string;
// An optional TTL (time to leave in milliseconds) for the entry to be removed from the cache.
// If not provided the cache will be never cleared.
expirationTimeMs?: number;
}
Decorator Example 1 (cache with no ttl):
import { memoizeAsync } from 'utils-decorators';
import { DataProvider, DataDto } from './data-provider';
class Example1 {
constructor(private readonly dataProvider: DataProvider) { }
@memoizeAsync()
getData(): Promise<DataDto>; {
return this.dataProvider.getData();
}
}
Function Example 1 (cache with no ttl):
import { memoizeAsyncify } from 'utils-decorators';
import { dataProvider } from './data-provider';
const memoizedDataProvider = memoizeAsyncify(dataProvider);
Decorator Example 2 (with a ttl only):
import { memoizeAsync } from 'utils-decorators';
import { DataProvider, DataDto } from './data-provider';
class Example2 {
constructor(private readonly dataProvider: DataProvider) { }
// a one hour ttl
@memoizeAsync(1000 * 60 * 60)
getData(): Promise<DataDto>; {
return this.dataProvider.getData();
}
}
Function Example 2 (with a ttl only):
import { memoizeAsyncify, Cache } from 'utils-decorators';
import { dataProvider } from './data-provider';
// a one hour ttl
const memoizedDataProvider = memoizeAsyncify(dataProvider, 1000 * 60 * 60);
Decorator Example 3 (with a custom cache):
import { memoizeAsync, Cache } from 'utils-decorators';
import { DataProvider, DataDto } from './data-provider';
class CustomCache implements Cache<number> {
set: (key: string, value: number) => {...};
get: (key: string) => number | null => {...}
delete: (key: string) => void => {...}
has: (key: string) => boolean => {...}
}
const customCache = new CustomCache();
class Example3 {
constructor(private readonly dataProvider: DataProvider) { }
@memoizeAsync({
cache: customCache,
expirationTimeMs: 1000 * 60 * 60,
})
getData(): Promise<DataDto>; {
return this.dataProvider.getData();
}
}
Function Example 3 (with a custom cache):
import { memoizeAsyncify } from 'utils-decorators';
import { dataProvider } from './data-provider';
const customCache: Cache<number> = {
set: (key: string, value: number) => {...};
get: (key: string) => number | null => {...}
delete: (key: string) => void => {...}
has: (key: string) => boolean => {...}
}
const memoizedDataProvider = memoizeAsyncify(dataProvider, {
cache: customCache,
expirationTimeMs: 1000 * 60 * 60,
});
Decorator Example 4 (with an async cache):
import { memoizeAsync, AsyncCache } from 'utils-decorators';
import { DataProvider, DataDto } from './data-provider';
class CustomCache implements AsyncCache<number> {
set: (key: string, value: number): Promise<void> => {...};
get: (key: string) => Promise<number | null> => {...}
delete: (key: string) => Promise<void> => {...}
has: (key: string) => Promise<boolean> => {...}
}
const customCache = new CustomCache();
class Example4 {
constructor(private readonly dataProvider: DataProvider) { }
@memoizeAsync({
cache: customCache,
expirationTimeMs: 1000 * 60 * 60,
})
getData(): Promise<DataDto>; {
return this.dataProvider.getData();
}
}
Function Example 4 (with an async cache):
import { memoizeAsyncify, AsyncCache } from 'utils-decorators';
import { dataProvider } from './data-provider';
const customCache: AsyncCache<number> = {
set: (key: string, value: number): Promise<void> => {...};
get: (key: string) => Promise<number | null> => {...}
delete: (key: string) => Promise<void> => {...}
has: (key: string) => Promise<boolean> => {...}
}
const memoizedDataProvider = memoizeAsyncify(dataProvider, {
cache: customCache,
expirationTimeMs: 1000 * 60 * 60,
});