この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
InversifyJSはおそらくJS/TSで一番使われているDIコンテナライブラリだと思います。
こちら、かなり機能が多いのですが、
- toConstantValue()
- toDynamicValue()
- toDynamicValue().inSingleScope()
を押さえて使い分ければ大体のユースケースに対応できるのでは?という気がしたので紹介します。
なお、個人的な好みによりDecoratorは使わない方向とします。
環境
- node 16.14.0
- inversify 6.0.1
toConstantValue()
toConstantValue()は一番シンプルに値を登録する方法です。
import { Container } from 'inversify'
const container = new Container()
container.bind('CONSTANT').toConstantValue('Something')
const gotValue = container.get('CONSTANT')
console.log(gotValue) // => 'Something' を出力
'CONSTANT'
というキーに 'Something'
という文字列の値を登録して取得する例です。メソッドの名前の通り定数をセットするような感じです。
toDynamicValue()
toDynamicValue()は値を返す関数を登録します。登録した関数は値を取得する際に実行されるため、遅延評価の登録方法といえそうです。
import { Container } from 'inversify'
const container = new Container()
container.bind('DYNAMIC').toDynamicValue(() => {
return 'Something'
})
const gotValue = container.get('DYNAMIC')
console.log(gotValue) // => 'Something' を出力
また、toDynamicValue()は他の登録値を取得して値を返すといったことができます。引数の context
に container
プロパティがあるので、そこから get()
メソッドを使用することができます。
container.bind('DYNAMIC_1').toDynamicValue(() => {
return 'Something'
})
container.bind('DYNAMIC_2').toDynamicValue((context) => {
return context.container.get('DYNAMIC_1')
})
このようにDYNAMIC_1に依存するDYNAMIC_2の値を解決することができます。
そして、toDynamicValue()は取得される度に関数が実行されます。次に例を示します。
container.bind('DYNAMIC').toDynamicValue(() => {
console.log('Run toDynamicValue callback') // デバッグのために追加
return 'Something'
})
const gotValue = container.get('DYNAMIC') // => 'Run toDynamicValue callback' を出力
console.log(gotValue) // => 'Something' を出力
container.get('DYNAMIC') // => 'Run toDynamicValue callback' を出力
container.get('DYNAMIC') // => 'Run toDynamicValue callback' を出力
デバッグのために関数内に console.log('Run toDynamicValue callback')
を仕込みました。この状態で container.get('DYNAMIC')
を3度行うと 'Run toDynamicValue callback'
が3行出力されます。つまり3回関数が実行されています。
この点、1度目の取得で値をキャッシュして、2度目の取得以降はキャッシュ値を返したいニーズもあると思います。そのような場合は次に紹介するtoDynamicValue().inSingleScope()が使えます。
toDynamicValue().inSingleScope()
上のサンプルにinSingletonScope()を追加したコードが下記です。
import { Container } from 'inversify'
const container = new Container()
container
.bind('DYNAMIC')
.toDynamicValue(() => {
console.log('Run toDynamicValue callback')
return 'Something'
})
.inSingletonScope() // 追加
const gotValue = container.get('DYNAMIC') // => 'Run toDynamicValue callback' を出力
console.log(gotValue) // => 'Something' を出力
container.get('DYNAMIC') // => 出力なし
container.get('DYNAMIC') // => 出力なし
このようにしてあげると、2度目の取得以降は 'Run toDynamicValue callback'
を出力しないため、関数が一度しか実行されていないことがわかります。
まとめ
3つのAPIを紹介しましたが、この中でも特に toDynamicValue().inSingleScope()
を多用すれば
- 不要なインスタンス生成を減らせる
- 2度目の取得以降はキャッシュを返す
という点からパフォーマンス面で良いのではないかと思いました。
参考になれば幸いです。