Skip to content

Commit

Permalink
add memoize config to add custom cache type
Browse files Browse the repository at this point in the history
  • Loading branch information
steelsojka committed Apr 27, 2017
1 parent 0ce91dc commit 735eb58
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 9 deletions.
27 changes: 21 additions & 6 deletions src/applicators/MemoizeApplicator.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
import { isFunction, isObject } from 'lodash';

import { Applicator, ApplicateOptions } from './Applicator';
import { resolveFunction } from '../utils';

export class MemoizeApplicator extends Applicator {
apply({ value, instance, config: { execute }, args, target }: ApplicateOptions): any {
if (!instance) {
return execute(value, ...args);
let resolver = resolveFunction(
isFunction(args[0]) ? args[0] : isObject(args[0]) ? args[0].resolver : args[0],
instance,
target,
false
);

if (resolver && instance) {
resolver = resolver.bind(instance);
}

let resolver = resolveFunction(args[0], instance, target, false);
const memoized = resolver ? execute(value, resolver) : execute(value);

if (resolver) {
resolver = resolver.bind(instance);
if (isObject(args[0])) {
const { cache, type } = args[0];

if (cache) {
memoized.cache = cache;
} else if (isFunction(type)) {
memoized.cache = new type();
}
}

return resolver ? execute(value, resolver) : execute(value);
return memoized;
}
}
34 changes: 34 additions & 0 deletions src/memoize.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,38 @@ describe('memoize', () => {
expect(_spy.callCount).to.equal(2);
});
});

describe('with custom map type', () => {
it('should create the map of type', () => {
class MyClass {
@Memoize({ type: WeakMap })
fn(item: any): any {
return item.value;
}
}

const myClass = new MyClass();

expect((<any>myClass.fn).cache).to.be.an.instanceOf(WeakMap);
});
});

describe('with custom cache', () => {
it('should use the provided map', () => {
const cache = new Map();

class MyClass {
@Memoize({ cache })
fn(item: any): any {
return item.value;
}
}

const myClass = new MyClass();
const myClass2 = new MyClass();

expect((<any>myClass.fn).cache).to.equal(cache);
expect((<any>myClass2.fn).cache).to.equal(cache);
});
});
});
3 changes: 2 additions & 1 deletion src/memoize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {
ResolvableFunction
} from './factory';
import { MemoizeApplicator } from './applicators';
import { MemoizeConfig } from './shared';

export const Memoize: (resolver?: ResolvableFunction) => LodashMethodDecorator = DecoratorFactory.createInstanceDecorator(
export const Memoize: (resolver?: ResolvableFunction|MemoizeConfig<any, any>) => LodashMethodDecorator = DecoratorFactory.createInstanceDecorator(
new DecoratorConfig(memoize, new MemoizeApplicator())
);
export { Memoize as memoize };
Expand Down
3 changes: 2 additions & 1 deletion src/memoizeAll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { memoize } from 'lodash';

import { DecoratorConfig, DecoratorFactory, LodashMethodDecorator } from './factory';
import { MemoizeApplicator } from './applicators';
import { MemoizeConfig } from './shared';

/**
* Memoizes a function on the prototype instead of the instance. All instances of the class use the same memoize cache.
* @param {Function} [resolver] Optional resolver
*/
export const MemoizeAll: (resolver?: Function) => LodashMethodDecorator = DecoratorFactory.createDecorator(
export const MemoizeAll: (resolver?: Function|MemoizeConfig<any, any>) => LodashMethodDecorator = DecoratorFactory.createDecorator(
new DecoratorConfig(memoize, new MemoizeApplicator())
);
export { MemoizeAll as memoizeAll };
Expand Down
16 changes: 15 additions & 1 deletion src/shared.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DecoratorConfig } from './factory';
import { DecoratorConfig, ResolvableFunction } from './factory';

export interface DebounceOptions {
wait?: number;
Expand All @@ -18,4 +18,18 @@ export interface ApplicateOptions {
export interface ThrottleOptions {
leading?: boolean;
trailing?: boolean;
}

export interface MemoizeMap<T, U> {
get(key: T): U;
has(key: T): boolean;
set(key: T, value: U): void;
delete(key: T): void;
clear?(): void;
}

export interface MemoizeConfig<T, U> {
resolver?: ResolvableFunction;
type?: { new (...args: any[]): MemoizeMap<T, U> };
cache?: MemoizeMap<T, U>;
}

0 comments on commit 735eb58

Please sign in to comment.