Gathering detailed insights and metrics for @fantastic-utils/memo
Gathering detailed insights and metrics for @fantastic-utils/memo
powerful memorization lib, which inspired by memoize-one, proxy-memoize
npm install @fantastic-utils/memo
Typescript
Module System
Node Version
NPM Version
72.8
Supply Chain
97.8
Quality
75.2
Maintenance
100
Vulnerability
100
License
JavaScript (57.3%)
TypeScript (42.7%)
Love this project? Help keep it running — sponsor us today! 🚀
Total Downloads
1,193
Last Day
2
Last Week
6
Last Month
33
Last Year
521
1 Stars
6 Commits
1 Watching
1 Branches
1 Contributors
Minified
Minified + Gzipped
Latest Version
1.0.0
Package Id
@fantastic-utils/memo@1.0.0
Unpacked Size
32.73 kB
Size
7.88 kB
File Count
7
NPM Version
8.19.3
Node Version
16.19.1
Publised On
08 Mar 2023
Cumulative downloads
Total Downloads
Last day
100%
2
Compared to previous day
Last week
-25%
6
Compared to previous week
Last month
65%
33
Compared to previous month
Last year
-22.5%
521
Compared to previous year
A memo library which can be used in many cases, this library is inspired by memoize-one
, proxy-memoize
, async-memoize-one
, and have more feature to support different use cases.
memoize-one
and proxy-memoize
are great, but they are only for some general cases, as many tools and libraries are designed in a special way, so some corner case can't be handled correctly, so this library build up for solving this issue.
memoize-one
: use shallow compare as a straightforward way.proxy-memoize
: is build on proxy-compare
which author designed as a stateless library, and proxy-memoize
use its markup key to compare old object and new object.As many library now use the Proxy
feature, and Proxy
always work with Scope
feature, so we can't always simply treat object as a immutable value, especially in some library design, maybe that's we wanted, so This library give an another choice to control the logic, not just a dead code.
1npm install @fantastic-utils/memo 2
this library contains memo
and memoAsync
.
1import { memo, memoAsync, original } from '@fantastic-utils/memo'; 2 3// Basic cache 4const add = (a, b) => a + b; 5const memoAdd = memo(add); 6memoAdd(1, 2); // 3 7memoAdd(1, 2); // 3 from cache 8 9// Deep cache 10const add = (objA, arrayB) => objA.a + objB[0]; 11const memoAdd = memo(add); 12memoAdd({ a: 1 }, [2]); // 3 13memoAdd({ a: 1 }, [2]); // 3 from cache 14 15// Async cache 16const add = async (a, b) => await (a + b); 17const memoAdd = memoAsync(add); 18await memoAdd(1, 2); // 3 19await memoAdd(1, 2); // 3 20 21// Shallow compare 22const add = (objA, b) => objA.a + b; 23const memoAdd = memo(add, { objectShallowCompare: true }); 24const obj = { a: 1 }; 25memoAdd(obj, 2); // 3 26obj.a = 2; 27memoAdd(obj, 2); // 3 from cache 28 29// console log raw data, as argument is wrapped by proxy 30const add = (objA, b) => { 31 console.log(original(objA)); 32 return objA.a + b; 33};
React
pure component1import { memo, original } from '@fantastic-utils/memo'; 2 3const TestComponent = memo((props) => { 4 // Take care of console.log, as console.log will construct proxy values 5 // use original to get the raw value. 6 // Note that `.detail` will be marked as used 7 console.log(original(props.detail)); 8 return ( 9 <> 10 <h3>{props.detail.address}</h3> 11 </> 12 ); 13}); 14 15export default TestComponent;
1// memo function 2memo(fn, memo: MemoConfig): fn 3// async memo function 4memoAsync(fn, memo: MemoConfig): fn 5// Get raw object, as arg are wrapped by proxy 6original(arg): object
1export interface MemoConfig { 2 objectShallowCompare?: boolean; 3 shouldCompare?: (args?: any[], cachedArgsCfg?: NormalizeArgCfg[]) => boolean; 4 isChanged?: (args?: any[], cachedArgsCfg?: NormalizeArgCfg[]) => boolean; 5} 6 7/** 8 * @param t The Type 9 * @param v The normalized value 10 * @param r The raw value 11 * @param a The affected info 12 */ 13export interface NormalizeArgCfg { 14 t: string; 15 v: unknown; 16 r: unknown; 17 a: Affected; 18}
API: function(newArgs: any[], cachedArgsCfg: NormalizeArgCfg[]): boolean
.
shouldCompare
let user to determine whether to compare args with default compare logic or not,
1import { memo } from '@fantastic-utils/memo'; 2 3const add = (a, b) => a + b; 4const memoAdd = memo(add, { 5 shouldCompare(newArgs, cachedArgCfg) { 6 return newArgs[0] === 1; 7 }, 8}); 9memoAdd(1, 2); // 3 10memoAdd(1, 2); // 3 from cache 11expect(memoAdd).toBeCalledTimes(1); // only call once
API: function(newArgs: any[], cachedArgsCfg: NormalizeArgCfg[]): boolean
.
isChanged
is a high level api than shouldCompare
to control all compare logic.
1import { memo } from '@fantastic-utils/memo'; 2 3const add = (a, b) => a + b; 4const memoAdd = memo(add, { 5 isChanged(newArgs, cachedArgCfg) { 6 return newArgs[0] === 1; 7 }, 8}); 9memoAdd(1, 2); // 3 10memoAdd(1, 2); // 3 from re-run function 11expect(memoAdd).toBeCalledTimes(2); // call twice
shouldCompare
and isChanged
The biggest difference between shouldCompare
and isChanged
is that shouldCompare
control how to use cache, and isChanged
control how to compare. sometimes shouldCompare
used to improve performance, and isChanged
used to customize compare logic.
Please refer to above code see the compare detail.
Benchmark code pls refer to __benchmark__
folder.
1@fantastic-utils/memo deep x 82,670,951 ops/sec ±2.32% (85 runs sampled) 2proxy-memoize deep x 779,043 ops/sec ±3.83% (85 runs sampled) 3memoize-state deep x 22,624,061 ops/sec ±1.82% (81 runs sampled) 4 5Fastest is @fantastic-utils/memo deep
1@fantastic-utils/memo shallow x 26,180,311 ops/sec ±1.04% (89 runs sampled) 2proxy-memoize shallow x 1,120,131 ops/sec ±1.29% (86 runs sampled) 3memoize-one shallow x 17,569,314 ops/sec ±1.66% (83 runs sampled) 4memoize-state shallow x 18,697,192 ops/sec ±3.24% (86 runs sampled) 5 6Fastest is @fantastic-utils/memo shallow
1$ npm install
1$ npm run dev 2$ npm run build
MIT
No vulnerabilities found.
No security vulnerabilities found.