abcdefGets

ゲッツ!

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というシンプルな形でまとめられてよかった。
使い勝手も悪くないので結構重宝している。