Moize
The consistently-fast, complete memoization solution for JS
Install / Use
/learn @planttheidea/MoizeREADME
[!CAUTION] This library has been deprecated in favor of
micro-memoize, which as-of version 5 incorporates most of the functionality that this library offers at nearly half the size and better speed. It is recommended to migrate tomicro-memoize@latest, and you can use the migration guide to help with any specific changes to your codebase.
<img src="https://img.shields.io/badge/build-passing-brightgreen.svg"/> <img src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"/> <img src="https://img.shields.io/badge/license-MIT-blue.svg"/>moize
moize is a consistently blazing fast memoization library for JavaScript. It handles multiple parameters (including default values) without any additional configuration, and offers a large number of options to satisfy any number of potential use-cases.
- Importing
- Usage
- Configuration options
- Usage with shortcut methods
- useMoize hook
- Composition
- Collecting statistics
- Introspection
- Direct cache manipulation
- Benchmarks
- Filesize
- Browser support
- Development
$ npm i moize --save
Importing
ESM in browsers
import moize from 'moize';
ESM in NodeJS
import moize from 'moize/mjs/index.mjs';
CommonJS
const moize = require('moize');
Usage
import moize from 'moize';
const method = (a: number, b: number) => a + b;
const memoized = moize(method);
memoized(2, 4); // 6
memoized(2, 4); // 6, pulled from cache
All parameter types are supported, including circular objects, functions, etc. There are also a number of shortcut methods to memoize for unique use-cases.
Configuration options
moize optionally accepts an object of options as either the second parameter or as the first step in a curried function:
// inline
moize(fn, options);
// curried
moize(options)(fn);
The full shape of these options:
type Options = {
// is the cache based on deep equality of each key argument
isDeepEqual: boolean;
// is the result a promise
isPromise: boolean;
// is the result a React component
isReact: boolean;
// should the parameters be serialized instead of directly referenced
isSerialized: boolean;
// is the cache based on shallow equality of each key argument
isShallowEqual: boolean;
// custom method to compare equality between two key arguments
matchesArg: (cachedKeyArg: any, keyArg: any) => boolean;
// custom method to compare equality across all key arguments
matchesKey: (cachedKey: any[], key: any[]) => boolean;
// amount of time in milliseconds before the cache will expire
maxAge: number;
// maximum number of arguments passed to use as key for caching
maxArgs: number;
// maximum size of cache for this method
maxSize: number;
// method fired when a new entry is added to cache
onCacheAdd: (
cache: moize.Cache,
options: moize.Options,
moized: (...args: any[]) => any
) => void;
// method fire when either a new entry is added to cache or the LRU ordering of the cache has changed
onCacheChange: (
cache: moize.Cache,
options: moize.Options,
moized: (...args: any[]) => any
) => void;
// method fired when an existing entry in cache is used
onCacheHit: (
cache: moize.Cache,
options: moize.Options,
moized: (...args: any[]) => any
) => void;
// method to fire when a cache entry expires (in combination with maxAge)
onExpire: (key: any[]) => void;
// the unique identifier to give the memoized method when collecting statistics
profileName: string;
// method to serialize the arguments to build a unique cache key
serializer: (key: any[]) => string;
// method to transform the args into a custom format for key storage in cache
transformArgs: (key: any[]) => any[];
// should the cache entry be refreshed by calling the underlying function with the same parameters and
// updating the value stored in cache to be the new result
updateCacheForKey: (key: any[]) => boolean;
// should the cache entry's expiration be refreshed when the cache entry is hit (in combination with maxAge)
updateExpire: boolean;
};
All default values can be found here.
isDeepEqual
defaults to false
Should deep equality be used to compare cache each key argument.
type Arg = {
one: {
nested: string;
};
two: string;
};
const fn = ({ one, two }: Arg) => [one, two];
const memoized = moize(fn, { isDeepEqual: true });
memoized({ one: { nested: 'one' }, two: 'two' });
memoized({ one: { nested: 'one' }, two: 'two' }); // pulls from cache
This is also available via the shortcut method of moize.deep
const memoized = moize.deep(fn);
isPromise
defaults to false
Is the computed value in the function a Promise.
const fn = async (item: Promise<string>) => await item;
const memoized = moize(fn, { isPromise: true });
This is also available via the shortcut method of moize.promise.
const memoized = -moize.promise(fn);
The Promise itself will be stored in cache, so that cached returns will always maintain the Promise contract. For common usage reasons, if the Promise is rejected, the cache entry will be deleted.
isReact
defaults to false
Is the function passed a stateless functional React component.
type Props = {
one: string;
two: number;
};
const Component = ({ one, two }: Props) => (
<div>
{one}: {two}
</div>
);
const MemoizedFoo = moize(Component, { isReact: true });
This is also available via the shortcut method of moize.react.
const MemoizedFoo = moize.react(Component);
The method will do a shallow equal comparison of both props and legacy context of the component based on strict equality. If you want to do a deep equals comparison, set isDeepEqual to true.
NOTE: This will memoize on each instance of the component passed, which is equivalent to PureComponent or React.memo. If you want to
memoize on all instances (which is how this option worked prior to version 6), use the following options:
const memoized = moize(Component, { isShallowEqual: true, maxArgs: 2 });
isSerialized
defaults to false
Serializes the parameters passed into a string and uses this as the key for cache comparison.
const fn = (mutableObject: { one: Record<string, any> }) =>
mutableObject.property;
const memoized = moize(fn, { isSerialized: true });
This is also available via the shortcut method of moize.serialize.
const memoized = moize.serialize(fn);
If serialize is combined with either maxArgs or transformArgs, the following order is used:
- limit by
maxArgs(if applicable) - transform by
transformArgs(if applicable) - serialize by
serializer
NOTE: This is much slower than the default key storage, and usually the same requirements can be meet with isDeepEqual, so use at your discretion.
isShallowEqual
defaults to false
Should shallow equality be used to compare cache each key argument.
type Arg = {
one: string;
two: string;
};
const fn = ({ one, two }: Arg) => [one, two];
const memoized = moize(fn, { isShallowEqual: true });
memoized({ one: 'one', two: 'two' });
memoized({ one: 'one', two: 'two' }); // pulls from cache
This is also available via the shortcut method of moize.shallow
const memoized = moize.shallow(fn);
matchesArg
_defaults to SameValueZero equ
Related Skills
node-connect
347.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
108.7kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
347.9kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
347.9kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
