Skip to content

chriscdn/memoize

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@chriscdn/memoize

Memoize a synchronous or asynchronous function.

Installing

Using npm:

npm install @chriscdn/memoize

Using yarn:

yarn add @chriscdn/memoize

Usage

import { Memoize } from "@chriscdn/memoize";

The Memoize function can be used to memoize a synchronous or asynchronous function.

The cache is powered by quick-lru. Each call to Memoize creates a new cache instance.

The Memoize function prevents duplicate evaluations by ensuring that multiple calls with the same cache key are processed only once. This includes asynchronous functions.

By default, the cache key is generated by calling JSON.stringify() on the function arguments. This behavior can be customized (see below).

Example (Synchronous)

To memoize a function:

const _add = (x: number, y: number) => x + y;

const add = Memoize(_add);

The add function has the same interface as _add:

const result = add(5, 7);
// 12

You can also define the function in a single line:

const add = Memoize((x: number, y: number) => x + y);

Example (Asynchronous)

Memoizing an asynchronous function is similar:

const _add = async (x: number, y: number) => x + y;

const add = Memoize(_add);

const result = await add(5, 7);
// 12

Options

The Memoize function accepts an options parameter to control the cache behavior:

const add = Memoize(_add, options);

Available options (with defaults):

const options = {
  // The maximum number of items in the cache.
  maxSize: 1000,

  // The maximum duration (in milliseconds) an item can remain in the cache. If set to `undefined`, the item will not expire due to time constraints.
  maxAge: undefined,

  // A synchronous function that returns `true` or `false` to determine whether to add the returnValue to the cache.
  shouldCache: (returnValue: Return, key: string) => true,

  // A synchronous function to generate a cache key (must return a string).
  resolver: (...args) => JSON.stringify(args),
};

Note: Memoize works with both synchronous and asynchronous functions. However, when using the shouldCache callback with an asynchronous function, the returnValue passed to shouldCache is a Promise. This is effectively useless since caching decisions should be based on the resolved value.

To address this, use MemoizeAsync instead. It has the same interface as Memoize, but works with asynchronous functions and passes the resolved value to shouldCache.

import { MemoizeAsync } from "@chriscdn/memoize";

Cache

The underlying quick-lru instance is accessible via the .cache property on the memoized function:

const add = Memoize(_add);
const result = await add(5, 7);

console.log(add.cache.size === 1);
// true

// Clear the cache
add.cache.clear();

The values null and undefined are cached by default, but this behavior can be adjusted using the shouldCache option.

Class Methods

Class methods can also be memoized, but this requires overriding the method within the constructor. Ensure you bind the method to the instance to maintain the correct context.

Here's an example where the add method is memoized by reassigning it within the constructor. This approach preserves access to instance properties (like count) and maintains the correct method signature in TypeScript:

class AddClass {
  count: number = 0;

  constructor() {
    this.add = Memoize(this.add.bind(this));
  }

  add(x: number, y: number) {
    this.count += 1;
    return x + y;
  }
}

Each memoized method in each class instance maintains its own cache.

Tests

Run the tests using:

yarn test

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published