js-loading-cache
A loading cache implementation with possibility to set a maximum size and timeout entries
Usage
import LoadingCache from '@aftonbladet/loading-cache';
import request from 'co-request';
const cache = new LoadingCache(url => request(url), {
maxAge: 1000 * 60 * 5,
maxEntries: 1000
});
cache.get('http://example.com')
.then(result => {
});
API
Constructor
constructor([options])
Creates a new LoadingCache instance
-
{object} options
: A config object to configure how the cache behaves:-
{number} maxEntries
: The maximum total amount of entries in the cache. See Eviction for how entries are removed from the cache. -
{number} maxAge
: The maximum time (in milliseconds) an entry remains in the cache. If provided it should be a number larger than 0. -
{number} freshAge
: The amount of time in milliseconds entries are considered to be fresh. See Serving stale entries for details. -
{Function} defaultLoader
: This function is called with the key to populate if the value is not found in the cache. The function must return a value synchronously, but it is ok to return aPromise
if works needs to be done async.
-
Methods
get(key, [loaderFn])
Fetches an item from the cache. If key
is not already in the cache then loaderFn
, provided in the constructor, is
invoked and the cache populated for that key
.
Get always returns a Promise
for a value, to allow the loader function to work asynchronously.
-
{*} key
: Any value that is a valid key for aMap
works as a key in theLoadingCache
. -
{Function} [loaderFn]
: Optional ifdefaultLoader
was specified when constructing the cache instance. This function is called with the key to populate if the value is not found in the cache. The function must return a value synchronously, but it is ok to return aPromise
if works needs to be done async. -
Returns:
Promise{*}
- The value returned byloaderFn
wrapped in aPromise
.
has(key)
Checks if a key has an entry in the cache. Does NOT invoke the loader function if the key is not in th cache.
-
{*} key
: The key to check in the cache -
Returns:
{boolean}
-true
ifkey
is in the cache,false
otherwise
clear()
Empties the cache
Properties
{number} size
The current number of entries in the cache
{number|undefined} maxEntries
The maximum amount of entries allowed in the cache
{number|undefined} maxAge
The maximum amount of time entries are allowed to stay in the cache in milliseconds.
{number|undefined} freshAge
The amount of time in milliseconds entries are considered to be fresh. Entries that are older than freshAge
will
continue to be served (as long as they are not evicted by maxAge
), but the loaderFn
will trigger an update in
the background.
Note maxAge
need to be larger than freshAge
for this to have any effect.
Cache eviction
The default cache eviction strategy is based upon an LRU-scheme. This means that "hot" items that are fetched often have a higher chance to remain in the cache, while entries that are fetched only a few times will eventually be evicted from the cache.
NOTE: You must provide a value for maxEntries
for this to apply.
Additionally, entries can have a maxAge
. Cache entries that have expired are evicted before items are evicted due
to a cache size exceeding `maxEntries.
If you are not happy with the default eviction implementation, you can provide your own eviction strategy to the constructor. The cache expects to receive an object (or constructor function) with the following interface:
Serving stale entries
If both the maxAge
and freshAge
properties are set, the cache will be able to serve stale entries in the time
period after freshAge
but before maxAge
. The stale content will be served during the loaderFn
is busy updating
the cache entry or even if an error occurs in the loaderFn
.
This can be used to make sure that you always return a cached entry quickly and let the update continue in the background. It is also useful to be able to return stale content during a restart of a backing service or maybe a network glitch or similar.
Cache eviction API
constructor({maxEntries, maxAge, freshAge})
Constructs a new eviction strategy based upon the provided constructor function. You can either pass in the
constructor function, in which case you'll receive maxEntries
, maxAge
and freshAge
as an config object argument,
or you can construct the eviction API yourself and provide that object to the constructor of the LoadingCache
.
onLoad(key, val, entries)
Called after the cache received a value from the loaderFn
. Note that entries
has already been populated with
val
at this point.
-
{*} key
: The key ofval
, which is the loaded value. -
{Promise<*>} val
: APromise
for the eventual value ofval
. -
{Map} entries
: All the entries in the cache, includingval
.
onGet(key, val, entries)
Called after key
was found in the cache. Here you can perform management tasks such as keeping track of which
keys are fetched etc.
-
{*} key
: The key that was fetched -
{Promise<*>} val
: APromise
for the eventual value ofval
corresponding tokey
. -
{Map} entries
: All the entries in the cache.
isValid(key, val, entries)
Called when key
has an entry in the cache, but before val
is returned to the caller.
-
{*} key
: The key that was fetched -
{Promise<*>} val
: APromise
for the eventual value ofval
corresponding tokey
. -
{Map} entries
: All the entries in the cache. -
Returns:
{boolean}
-true
ifval
is a valid entry forkey
,false
otherwise.