-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathmemoizer.ts
60 lines (50 loc) · 1.68 KB
/
memoizer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import {isEqualArgs} from 'core/comparer';
import {ResultFn} from 'core/generic';
interface ICachedResultFn<TEntry> {
result: TEntry;
cached: boolean;
first: boolean;
}
export function memoizeOne<TArgs extends any[], TEntry>(
fn: ResultFn<TArgs, TEntry>
): ResultFn<TArgs, TEntry> {
let lastArgs: any[] | null = null;
let lastResult: any;
return (...args: TArgs): TEntry =>
isEqualArgs(lastArgs, args)
? lastResult
: (lastArgs = args) && (lastResult = fn(...args));
}
export function memoizeOneFactory<TArgs extends any[], TEntry>(
fn: ResultFn<TArgs, TEntry>
): () => ResultFn<TArgs, TEntry> {
return () => memoizeOne(fn);
}
export function memoizeOneWithFlag<TArgs extends any[], TEntry>(
fn: ResultFn<TArgs, TEntry>
): ResultFn<TArgs, ICachedResultFn<TEntry>> {
let lastArgs: any[] | null = null;
let lastResult: any;
let isFirst = true;
return (...args: TArgs): ICachedResultFn<TEntry> => {
const res = isEqualArgs(lastArgs, args)
? {cached: true, first: isFirst, result: lastResult}
: {
cached: false,
first: isFirst,
result: (lastArgs = args) && (lastResult = fn(...args))
};
isFirst = false;
return res;
};
}
export function memoizeAll<TArgs extends any[], TEntry>(
fn: ResultFn<TArgs, TEntry>
): ResultFn<TArgs, TEntry> {
const cache: {args: TArgs; result: TEntry}[] = [];
return (...args: TArgs): TEntry => {
const entry = cache.find(e => isEqualArgs(e.args, args));
return (entry || cache[cache.push({args, result: fn(...args)}) - 1])
.result;
};
}