Go back to the main documentation page.
You can think of CachedFunction
as an advanced "memoize" function that you can call with any arguments, but also:
- verify whether a specific set of arguments is cached (
.isCached()
) - only get the cached value if it exists (
.getCached()
) - only get the fresh value, skipping the cache (but still caching the result) (
.getFresh()
) - delete a cached value (
.delete()
)
Type: string
The unique name that will be used in chrome.storage.local
combined with the function arguments, like cache:${key}:{arguments}
.
For example, these two calls:
const pages = new CachedFunction('pages', {updater: fetchText});
await pages.get();
await pages.get('./contacts');
await pages.get('./about', 2);
await pages.get(); // Will be retrieved from cache
Will call fetchText
3 times and create 3 items in the storage:
{
"cache:pages": "You're on the homepage",
"cache:pages:[\"./contacts\"]": "You're on the contacts page",
"cache:pages:[\"./about\",2]": "You're on the about page"
}
Required.
Type: async function
that returns a cacheable value.
Returning undefined
will delete the item from the cache.
Type: TimeDescriptor
Default: {days: 30}
The amount of time after which the cache item will expire after being each cache update.
Type: TimeDescriptor
Default: {days: 0}
(disabled)
Specifies how much longer an item should be kept in cache after its expiration. During this extra time, the item will still be served from cache instantly, but updater
will be also called asynchronously to update the cache. A later call will return the updated and fresher item.
const operate = new CachedFunction('posts', {
updater: operate,
maxAge: {
days: 10,
},
staleWhileRevalidate: {
days: 2,
},
});
await operate.get(); // It will run `operate` and cache it for 10 days
await operate.get(); // It will return the cache
/* 3 days later, cache is expired, but still there */
await operate.get(); // It will return the cache
// Asynchronously, it will also run `operate` and cache the new value for 10 more days
/* 13 days later, cache is expired and deleted */
await operate.get(); // It will run `operate` and cache it for 10 days
Type: (cachedValue) => boolean
Default: () => false
You may want to have additional checks on the cached value, for example after updating its format.
async function getContent(url) {
const response = await fetch(url);
return response.json(); // For example, you used to return plain text, now you return a JSON object
}
const content = new CachedFunction('content', {
updater: getContent,
// If it's a string, it's in the old format and a new value will be fetched and cached
shouldRevalidate: cachedValue => typeof cachedValue === 'string',
});
const json = await content.get('https://google.com');
// Even if it's cached as a regular string, the cache will be discarded and `getContent` will be called again
Type: (args: any[]) => string
Default: JSON.stringify
By default, the function’s arguments
JSON-stringified array will be used to create the cache key.
const posts = new CachedFunction('posts', {updater: fetchPosts});
const user = {id: 123, name: 'Fregante'};
await posts.get(user);
// Its result will be stored in the key 'cache:fetchPosts:[{"id":123,name:"Fregante"}]'
You can pass a cacheKey
function to customize how the key is generated, saving storage and making it more sensible:
const posts = new CachedFunction('posts', {
updater: fetchPosts,
cacheKey: (args) => args[0].id, // ✅ Use only the user ID
});
const user = {id: 123, name: 'Fregante'};
await posts.get(user);
// Its result will be stored in the key 'cache:fetchPosts:123'
This method is equivalent to calling your updater
function with the specified parameters, unless the result of a previous call is already in the cache:
const repositories = new CachedFunction('repositories', {updater: repoApi});
await repositories.get('fregante', 'doma'); // Will call repoApi('fregante', 'doma')
await repositories.get('fregante', 'doma'); // Will return the item from the cache
await repositories.get('fregante', 'webext-base-css'); // Will call repoApi('fregante', 'webext-base-css')
This updates the cache just like .get()
, except it always calls updater
regardless of cache state. It's meant to be used as a "refresh cache" action:
const repositories = new CachedFunction('repositories', {updater: repoApi});
await repositories.get('fregante', 'doma'); // Will call repoApi('fregante', 'doma')
await repositories.getFresh('fregante', 'doma'); // Will call repoApi('fregante', 'doma') regardless of cache state
This only returns the value of a previous .get()
call with the same arguemnts, but it never calls your updater
:
const repositories = new CachedFunction('repositories', {updater: repoApi});
await repositories.getCached('fregante', 'doma'); // It can be undefined
const repositories = new CachedFunction('repositories', {updater: repoApi});
await repositories.isCached('fregante', 'doma');
// => true / false
const repositories = new CachedFunction('repositories', {updater: repoApi});
await repositories.delete('fregante', 'doma');
This method should only be used if you want to override the cache with a custom value, but you should prefer get
or getFresh
instead, keeping the logic exclusively in your updater
function.
const repositories = new CachedFunction('repositories', {updater: repoApi});
// Will override the local cache for the `repoApi('fregante', 'doma')` call
await repositories.applyOverride(['fregante', 'doma'], {id: 134, lastUpdated: 199837738894});
MIT © Federico Brigante