@blumintinc/typescript-memoize 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +342 -342
- package/dist/es2015/memoize-decorator.d.ts +10 -10
- package/dist/es2015/memoize-decorator.js +218 -218
- package/dist/es2015/memoize-decorator.js.map +1 -1
- package/dist/memoize-decorator.d.ts +10 -10
- package/dist/memoize-decorator.js +249 -248
- package/dist/memoize-decorator.js.map +1 -1
- package/package.json +65 -65
- package/src/memoize-decorator.ts +251 -250
package/package.json
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@blumintinc/typescript-memoize",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Memoize decorator for Typescript with deep equality",
|
|
5
|
-
"main": "./dist/memoize-decorator.js",
|
|
6
|
-
"module": "./dist/es2015/memoize-decorator.js",
|
|
7
|
-
"typings": "./dist/memoize-decorator.d.ts",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"test": "karma start test/karma.config.js --single-run",
|
|
10
|
-
"prepublish": "npm run build && npm run build:es2015",
|
|
11
|
-
"clean": "rm -rf ./dist",
|
|
12
|
-
"build": "tsc",
|
|
13
|
-
"build:es2015": "tsc --module es2015 --target es2015 --outDir dist/es2015",
|
|
14
|
-
"tslint": "tslint --project .",
|
|
15
|
-
"eslint": "npm run tslint"
|
|
16
|
-
},
|
|
17
|
-
"private": false,
|
|
18
|
-
"publishConfig": {
|
|
19
|
-
"access": "public"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"dist",
|
|
23
|
-
"src"
|
|
24
|
-
],
|
|
25
|
-
"repository": {
|
|
26
|
-
"type": "git",
|
|
27
|
-
"url": "git+https://github.com/BluMintInc/typescript-memoize.git"
|
|
28
|
-
},
|
|
29
|
-
"keywords": [
|
|
30
|
-
"typescript",
|
|
31
|
-
"memoize",
|
|
32
|
-
"functional",
|
|
33
|
-
"decorator"
|
|
34
|
-
],
|
|
35
|
-
"author": "Joseph O'Connor",
|
|
36
|
-
"license": "MIT",
|
|
37
|
-
"bugs": {
|
|
38
|
-
"url": "https://github.com/BluMintInc/typescript-memoize/issues"
|
|
39
|
-
},
|
|
40
|
-
"homepage": "https://github.com/BluMintInc/typescript-memoize#readme",
|
|
41
|
-
"devDependencies": {
|
|
42
|
-
"@types/jasmine": "3.6.2",
|
|
43
|
-
"@types/node": "14.14.9",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"karma": "
|
|
48
|
-
"karma-
|
|
49
|
-
"karma-
|
|
50
|
-
"karma-jasmine": "
|
|
51
|
-
"karma-
|
|
52
|
-
"karma-
|
|
53
|
-
"karma-
|
|
54
|
-
"karma-
|
|
55
|
-
"karma-
|
|
56
|
-
"karma-typescript": "5.
|
|
57
|
-
"source-map-loader": "1.1.2",
|
|
58
|
-
"tslib": "2.0.3",
|
|
59
|
-
"tslint": "6.1.3",
|
|
60
|
-
"typescript": "4.1.2"
|
|
61
|
-
},
|
|
62
|
-
"dependencies": {
|
|
63
|
-
"fast-deep-equal": "^
|
|
64
|
-
}
|
|
65
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@blumintinc/typescript-memoize",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Memoize decorator for Typescript with deep equality",
|
|
5
|
+
"main": "./dist/memoize-decorator.js",
|
|
6
|
+
"module": "./dist/es2015/memoize-decorator.js",
|
|
7
|
+
"typings": "./dist/memoize-decorator.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"test": "karma start test/karma.config.js --single-run",
|
|
10
|
+
"prepublish": "npm run build && npm run build:es2015",
|
|
11
|
+
"clean": "rm -rf ./dist",
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"build:es2015": "tsc --module es2015 --target es2015 --outDir dist/es2015",
|
|
14
|
+
"tslint": "tslint --project .",
|
|
15
|
+
"eslint": "npm run tslint"
|
|
16
|
+
},
|
|
17
|
+
"private": false,
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"src"
|
|
24
|
+
],
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/BluMintInc/typescript-memoize.git"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"typescript",
|
|
31
|
+
"memoize",
|
|
32
|
+
"functional",
|
|
33
|
+
"decorator"
|
|
34
|
+
],
|
|
35
|
+
"author": "Joseph O'Connor",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/BluMintInc/typescript-memoize/issues"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://github.com/BluMintInc/typescript-memoize#readme",
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/jasmine": "3.6.2",
|
|
43
|
+
"@types/node": "14.14.9",
|
|
44
|
+
"es6-shim": "0.35.6",
|
|
45
|
+
"jasmine-core": "3.6.0",
|
|
46
|
+
"karma": "6.3.16",
|
|
47
|
+
"karma-chrome-launcher": "3.1.0",
|
|
48
|
+
"karma-es6-shim": "1.0.0",
|
|
49
|
+
"karma-jasmine": "4.0.1",
|
|
50
|
+
"karma-jasmine-html-reporter": "1.5.4",
|
|
51
|
+
"karma-junit-reporter": "2.0.1",
|
|
52
|
+
"karma-sourcemap-loader": "0.3.8",
|
|
53
|
+
"karma-spec-reporter": "0.0.32",
|
|
54
|
+
"karma-threshold-reporter": "0.1.15",
|
|
55
|
+
"karma-typescript": "5.5.4",
|
|
56
|
+
"karma-typescript-es6-transform": "^5.5.4",
|
|
57
|
+
"source-map-loader": "1.1.2",
|
|
58
|
+
"tslib": "2.0.3",
|
|
59
|
+
"tslint": "6.1.3",
|
|
60
|
+
"typescript": "4.1.2"
|
|
61
|
+
},
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"@blumintinc/fast-deep-equal": "^4.0.0"
|
|
64
|
+
}
|
|
65
|
+
}
|
package/src/memoize-decorator.ts
CHANGED
|
@@ -1,250 +1,251 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
interface MemoizeArgs {
|
|
4
|
-
expiring?: number;
|
|
5
|
-
hashFunction?: boolean | ((...args: any[]) => any);
|
|
6
|
-
tags?: string[];
|
|
7
|
-
useDeepEqual?: boolean;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
let
|
|
13
|
-
let
|
|
14
|
-
let
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
1
|
+
import equal from '@blumintinc/fast-deep-equal';
|
|
2
|
+
|
|
3
|
+
interface MemoizeArgs {
|
|
4
|
+
expiring?: number;
|
|
5
|
+
hashFunction?: boolean | ((...args: any[]) => any);
|
|
6
|
+
tags?: string[];
|
|
7
|
+
useDeepEqual?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export function Memoize(args?: MemoizeArgs | MemoizeArgs['hashFunction']) {
|
|
12
|
+
let hashFunction: MemoizeArgs['hashFunction'];
|
|
13
|
+
let duration: MemoizeArgs['expiring'];
|
|
14
|
+
let tags: MemoizeArgs['tags'];
|
|
15
|
+
let useDeepEqual: MemoizeArgs['useDeepEqual'] = true;
|
|
16
|
+
|
|
17
|
+
if (typeof args === 'object') {
|
|
18
|
+
hashFunction = args.hashFunction;
|
|
19
|
+
duration = args.expiring;
|
|
20
|
+
tags = args.tags;
|
|
21
|
+
useDeepEqual = args.useDeepEqual ?? true;
|
|
22
|
+
} else {
|
|
23
|
+
hashFunction = args;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return (target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => {
|
|
27
|
+
if (descriptor.value != null) {
|
|
28
|
+
descriptor.value = getNewFunction(descriptor.value, hashFunction, duration, tags, useDeepEqual);
|
|
29
|
+
} else if (descriptor.get != null) {
|
|
30
|
+
descriptor.get = getNewFunction(descriptor.get, hashFunction, duration, tags, useDeepEqual);
|
|
31
|
+
} else {
|
|
32
|
+
throw 'Only put a Memoize() decorator on a method or get accessor.';
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function MemoizeExpiring(expiring: number, hashFunction?: MemoizeArgs['hashFunction']) {
|
|
38
|
+
return Memoize({
|
|
39
|
+
expiring,
|
|
40
|
+
hashFunction
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const clearCacheTagsMap: Map<string, Map<any, any>[]> = new Map();
|
|
45
|
+
|
|
46
|
+
export function clear (tags: string[]): number {
|
|
47
|
+
const cleared: Set<Map<any, any>> = new Set();
|
|
48
|
+
for (const tag of tags) {
|
|
49
|
+
const maps = clearCacheTagsMap.get(tag);
|
|
50
|
+
if (maps) {
|
|
51
|
+
for (const mp of maps) {
|
|
52
|
+
if (!cleared.has(mp)) {
|
|
53
|
+
mp.clear();
|
|
54
|
+
cleared.add(mp);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return cleared.size;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// A wrapper around Map that uses deep equality for key comparison
|
|
63
|
+
class DeepEqualMap<K, V> {
|
|
64
|
+
private map = new Map<string, { key: K, value: V }>();
|
|
65
|
+
|
|
66
|
+
has(key: K): boolean {
|
|
67
|
+
const entries = Array.from(this.map.values());
|
|
68
|
+
for (const entry of entries) {
|
|
69
|
+
if (equal(entry.key, key)) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get(key: K): V | undefined {
|
|
77
|
+
const entries = Array.from(this.map.values());
|
|
78
|
+
for (const entry of entries) {
|
|
79
|
+
if (equal(entry.key, key)) {
|
|
80
|
+
return entry.value;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
set(key: K, value: V): this {
|
|
87
|
+
const entries = Array.from(this.map.entries());
|
|
88
|
+
for (const [serializedKey, entry] of entries) {
|
|
89
|
+
if (equal(entry.key, key)) {
|
|
90
|
+
this.map.delete(serializedKey);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const serializedKey = `${Date.now()}_${Math.random()}`;
|
|
96
|
+
this.map.set(serializedKey, { key, value });
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
clear(): void {
|
|
101
|
+
this.map.clear();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function getNewFunction(
|
|
106
|
+
originalMethod: () => void,
|
|
107
|
+
hashFunction?: MemoizeArgs['hashFunction'],
|
|
108
|
+
duration: number = 0,
|
|
109
|
+
tags?: MemoizeArgs['tags'],
|
|
110
|
+
useDeepEqual: boolean = true
|
|
111
|
+
) {
|
|
112
|
+
const propMapName = Symbol(`__memoized_map__`);
|
|
113
|
+
const propDeepMapName = Symbol(`__memoized_deep_map__`);
|
|
114
|
+
|
|
115
|
+
// The function returned here gets called instead of originalMethod.
|
|
116
|
+
return function (...args: any[]) {
|
|
117
|
+
let returnedValue: any;
|
|
118
|
+
|
|
119
|
+
// Get or create appropriate map based on deep equality requirement
|
|
120
|
+
if (useDeepEqual) {
|
|
121
|
+
if (!this.hasOwnProperty(propDeepMapName)) {
|
|
122
|
+
Object.defineProperty(this, propDeepMapName, {
|
|
123
|
+
configurable: false,
|
|
124
|
+
enumerable: false,
|
|
125
|
+
writable: false,
|
|
126
|
+
value: new DeepEqualMap<any, any>()
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
let myMap: DeepEqualMap<any, any> = this[propDeepMapName];
|
|
130
|
+
|
|
131
|
+
if (Array.isArray(tags)) {
|
|
132
|
+
for (const tag of tags) {
|
|
133
|
+
// Since DeepEqualMap doesn't match the Map interface exactly,
|
|
134
|
+
// we wrap it in a Map for tag clearing purposes
|
|
135
|
+
const mapWrapper = {
|
|
136
|
+
clear: () => myMap.clear()
|
|
137
|
+
} as any;
|
|
138
|
+
|
|
139
|
+
if (clearCacheTagsMap.has(tag)) {
|
|
140
|
+
clearCacheTagsMap.get(tag).push(mapWrapper);
|
|
141
|
+
} else {
|
|
142
|
+
clearCacheTagsMap.set(tag, [mapWrapper]);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let hashKey: any;
|
|
148
|
+
|
|
149
|
+
// If true is passed as first parameter, will automatically use every argument
|
|
150
|
+
if (hashFunction === true) {
|
|
151
|
+
hashKey = args;
|
|
152
|
+
} else if (hashFunction) {
|
|
153
|
+
hashKey = hashFunction.apply(this, args);
|
|
154
|
+
} else if (args.length > 0) {
|
|
155
|
+
hashKey = args.length === 1 ? args[0] : args;
|
|
156
|
+
} else {
|
|
157
|
+
hashKey = this;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Handle expiration
|
|
161
|
+
const timestampKey = { __timestamp: true, key: hashKey };
|
|
162
|
+
let isExpired: boolean = false;
|
|
163
|
+
|
|
164
|
+
if (duration > 0) {
|
|
165
|
+
if (!myMap.has(timestampKey)) {
|
|
166
|
+
isExpired = true;
|
|
167
|
+
} else {
|
|
168
|
+
let timestamp = myMap.get(timestampKey);
|
|
169
|
+
isExpired = (Date.now() - timestamp) > duration;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (myMap.has(hashKey) && !isExpired) {
|
|
174
|
+
returnedValue = myMap.get(hashKey);
|
|
175
|
+
} else {
|
|
176
|
+
returnedValue = originalMethod.apply(this, args);
|
|
177
|
+
myMap.set(hashKey, returnedValue);
|
|
178
|
+
if (duration > 0) {
|
|
179
|
+
myMap.set(timestampKey, Date.now());
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
// Original implementation with standard Map (shallow equality)
|
|
184
|
+
if (!this.hasOwnProperty(propMapName)) {
|
|
185
|
+
Object.defineProperty(this, propMapName, {
|
|
186
|
+
configurable: false,
|
|
187
|
+
enumerable: false,
|
|
188
|
+
writable: false,
|
|
189
|
+
value: new Map<any, any>()
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
let myMap: Map<any, any> = this[propMapName];
|
|
193
|
+
|
|
194
|
+
if (Array.isArray(tags)) {
|
|
195
|
+
for (const tag of tags) {
|
|
196
|
+
if (clearCacheTagsMap.has(tag)) {
|
|
197
|
+
clearCacheTagsMap.get(tag).push(myMap);
|
|
198
|
+
} else {
|
|
199
|
+
clearCacheTagsMap.set(tag, [myMap]);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (hashFunction || args.length > 0 || duration > 0) {
|
|
205
|
+
let hashKey: any;
|
|
206
|
+
|
|
207
|
+
// If true is passed as first parameter, will automatically use every argument, passed to string
|
|
208
|
+
if (hashFunction === true) {
|
|
209
|
+
hashKey = args.map(a => a.toString()).join('!');
|
|
210
|
+
} else if (hashFunction) {
|
|
211
|
+
hashKey = hashFunction.apply(this, args);
|
|
212
|
+
} else {
|
|
213
|
+
hashKey = args[0];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const timestampKey = `${hashKey}__timestamp`;
|
|
217
|
+
let isExpired: boolean = false;
|
|
218
|
+
if (duration > 0) {
|
|
219
|
+
if (!myMap.has(timestampKey)) {
|
|
220
|
+
// "Expired" since it was never called before
|
|
221
|
+
isExpired = true;
|
|
222
|
+
} else {
|
|
223
|
+
let timestamp = myMap.get(timestampKey);
|
|
224
|
+
isExpired = (Date.now() - timestamp) > duration;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (myMap.has(hashKey) && !isExpired) {
|
|
229
|
+
returnedValue = myMap.get(hashKey);
|
|
230
|
+
} else {
|
|
231
|
+
returnedValue = originalMethod.apply(this, args);
|
|
232
|
+
myMap.set(hashKey, returnedValue);
|
|
233
|
+
if (duration > 0) {
|
|
234
|
+
myMap.set(timestampKey, Date.now());
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
} else {
|
|
239
|
+
const hashKey = this;
|
|
240
|
+
if (myMap.has(hashKey)) {
|
|
241
|
+
returnedValue = myMap.get(hashKey);
|
|
242
|
+
} else {
|
|
243
|
+
returnedValue = originalMethod.apply(this, args);
|
|
244
|
+
myMap.set(hashKey, returnedValue);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return returnedValue;
|
|
250
|
+
};
|
|
251
|
+
}
|