Ecmascript decorator を使ってキャッシュする
表題の通り ES proposal のdecoratorをつかってメモ化のようなことをするライブラリを前に書いたので、 キレイにして、GitHubに公開した。
GitHub - brn/cache-decorator: javascript method/function cache decorator.
インストール
npm install cache-decorator --save
か
yarn add cache-decorator --save
使い方
メソッドのキャッシュ
For javascript/babel
import { cache, CacheType, CacheScope } from 'cache-decorator'; class Example { @cache({type: CacheType.MEMO, scope: CacheScope.INSTANCE}) expensiveCalc(args) {...} }
For typescript
tsconfig.json
{ "compilerOptions": { ... paths: { "cache-decorator": ["node_modules/cache-decorator/lib/index.d.ts"] } }, }
import { cache, CacheType, CacheScope } from 'cache-decorator'; class Example { @cache({type: CacheType.MEMO, scope: CacheScope.INSTANCE}) public expensiveCalc(args) {...} }
関数のキャッシュ
For javascript/babel
import { fcache, CacheType } from 'cache-decorator'; const cachedFn = fcache((args) => { ... }, {type: CacheType.MEMO})
For typescript
tsconfig.json
{ "compilerOptions": { ... paths: { "cache-decorator": ["node_modules/cache-decorator/lib/index.d.ts"] } }, }
import { cache, CacheType, CacheScope } from 'cache-decorator'; const cachedFn = fcache((args: Object) => { ... }, {type: CacheType.MEMO})
cacheのオプション引数
interface CacheOption { type?: CacheType; scope?: CacheScope; ttl?: number; compare?: (prev: any, next: any) => boolean; }
type: CacheType
default value: CacheType.SINGLETON
SINGLETON
- キャッシュを探す
- もしキャッシュがあればその値を変えす。なければメソッドを実行して、その結果を保存する.
- 結果を返す
MEMO
- キャッシュを引数のリストとともに検索し、保存されている引数リストと比較する.
- もし値が見つかれば結果を返し、見つからなければメソッドを実行し、結果と引数のペアをキャッシュに保存する。
- 結果を返す
scope: CacheScope
default value: CacheScope.INSTANCE
INSTANCE
キャッシュされた値はインスタンス毎の領域に保存され、インスタンス間で値が共有されない。
GLOBAL
すべてのキャッシュはグローバルな領域で管理され、すべてのインスタンスで値が共有される。
ttl: number
default value: null
指定されたミリ秒でキャッシュを破棄する。
compare: Function
default value: (a, b) => a.length === b.length && a.every((v, i) => v === b[i])
CacheType.MEMOが指定された場合に引数を比較するのに使う比較関数。
まとめ
メモ化は結構面倒なので、decoratorというシンプルな形でまとめられてよかった。
使い勝手も悪くないので結構重宝している。