Skip to content
Permalink
Browse files

Allow cleaning the memoize cache (#14)

* add cleaning to memoize

* 1.18.0

* 1.19.0
  • Loading branch information...
ftrimble authored and eugeneiiim committed Mar 15, 2019
1 parent c209e8e commit 105af91542b20bf6a9c7bebcdd7c44e142f4af65
Showing with 74 additions and 4 deletions.
  1. +1 −1 package-lock.json
  2. +1 −1 package.json
  3. +18 −2 src/memoize.ts
  4. +54 −0 test/memoize.test.ts

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -1,6 +1,6 @@
{
"name": "blend-promise-utils",
"version": "1.18.0",
"version": "1.19.0",
"author": "Blend",
"license": "MIT",
"homepage": "https://blend.github.io/promise-utils",
@@ -17,13 +17,13 @@ export function memoize<FnType extends Function>(
// tslint:disable-next-line:no-any (w/o type for Function args, can't assert a type here)
hasher: Function = (arg: any) => arg,
timeoutMs?: number,
): FnType {
): FnType & { reset: FnType; clear: () => void } {
// tslint:disable:no-any (unfortunately we can't give the FnType any more clarity or it limits
// what you can do with it)
const memos: Map<any, { value: any; expiration: number }> = new Map();
const queues: Map<any, Promise<any>> = new Map();

return ((async (...args: any[]): Promise<any> => {
const returnFn = ((async (...args: any[]): Promise<any> => {
const key: any = hasher(...args);
if (memos.has(key)) {
if (!timeoutMs || Date.now() < memos.get(key)!.expiration) {
@@ -46,6 +46,22 @@ export function memoize<FnType extends Function>(
queues.delete(key);
}
}) as any) as FnType;

const reset = (...args: any[]): void => {
const key = hasher(...args);
if (memos.has(key)) {
memos.delete(key);
}
};

const clear = (): void => {
memos.clear();
};

(returnFn as any).reset = reset;
(returnFn as any).clear = clear;

return returnFn as FnType & { reset: FnType; clear: () => void };
// tslint:enable:no-any (unfortunately we can't give the FnType any more clarity or it limits what
// you can do with it)
}
@@ -76,6 +76,60 @@ test('uses memos on subsequent calls (tested by coverage)', async t => {
t.is(cacheCount2, 100);
});

test('reset resets a memo', async t => {
const fnToMemoize = sandbox
.stub()
.onFirstCall()
.returns('first')
.onSecondCall()
.returns('second')
.onThirdCall()
.returns('third');
const memoized = promiseUtils.memoize(fnToMemoize);

const ret = await promiseUtils.map(_.range(100), val => memoized(1));
const ret2 = await promiseUtils.map(_.range(100), val => memoized(2));
const cacheCount = _.filter(ret, val => val === 'first').length;
const cacheCount2 = _.filter(ret2, val => val === 'second').length;
t.is(cacheCount, 100);
t.is(cacheCount2, 100);
memoized.reset(1);
const ret3 = await promiseUtils.map(_.range(100), val => memoized(2));
const ret4 = await promiseUtils.map(_.range(100), val => memoized(1));
const cacheCount3 = _.filter(ret3, val => val === 'second').length;
const cacheCount4 = _.filter(ret4, val => val === 'third').length;
t.is(cacheCount3, 100);
t.is(cacheCount4, 100);
});

test('clear resets all memos', async t => {
const fnToMemoize = sandbox
.stub()
.onFirstCall()
.returns('first')
.onSecondCall()
.returns('second')
.onThirdCall()
.returns('third')
.onCall(3)
.returns('fourth');
const memoized = promiseUtils.memoize(fnToMemoize);

const ret = await promiseUtils.map(_.range(100), val => memoized(1));
const ret2 = await promiseUtils.map(_.range(100), val => memoized(2));
const cacheCount = _.filter(ret, val => val === 'first').length;
const cacheCount2 = _.filter(ret2, val => val === 'second').length;
t.is(cacheCount, 100);
t.is(cacheCount2, 100);
memoized.clear();
const ret3 = await promiseUtils.map(_.range(100), val => memoized(2));
const ret4 = await promiseUtils.map(_.range(100), val => memoized(1));
const cacheCount3 = _.filter(ret3, val => val === 'third').length;
const cacheCount4 = _.filter(ret4, val => val === 'fourth').length;
t.is(cacheCount3, 100);
t.is(cacheCount4, 100);
});

test('uses memos on subsequent calls with timeout', async t => {
const fnToMemoize = sandbox
.stub()

0 comments on commit 105af91

Please sign in to comment.
You can’t perform that action at this time.