blob: 44eae7a6287090b0b356cb175224b0aaf8b1aec0 (
plain)
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
|
// @flow
import areInputsEqual from './are-inputs-equal';
export type EqualityFn = (newArgs: mixed[], lastArgs: mixed[]) => boolean;
// <ResultFn: (...any[]) => mixed>
// The purpose of this typing is to ensure that the returned memoized
// function has the same type as the provided function (`resultFn`).
// ResultFn: Generic type (which is the same as the resultFn).
// (...any[]): Accepts any length of arguments - and they are not checked
// mixed: The result can be anything but needs to be checked before usage
export default function memoizeOne<ResultFn: (...any[]) => mixed>(
resultFn: ResultFn,
isEqual?: EqualityFn = areInputsEqual,
): ResultFn {
let lastThis: mixed;
let lastArgs: mixed[] = [];
let lastResult: mixed;
let calledOnce: boolean = false;
// breaking cache when context (this) or arguments change
const result = function memoized(...newArgs: mixed[]) {
if (calledOnce && lastThis === this && isEqual(newArgs, lastArgs)) {
return lastResult;
}
// Throwing during an assignment aborts the assignment: https://codepen.io/alexreardon/pen/RYKoaz
// Doing the lastResult assignment first so that if it throws
// nothing will be overwritten
lastResult = resultFn.apply(this, newArgs);
calledOnce = true;
lastThis = this;
lastArgs = newArgs;
return lastResult;
};
return (result: any);
}
|