Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Angular DIスキ

Angular DIスキ

ng-kyoto Angular Meetup #5
の発表資料です。

Shinichi Kozake

March 20, 2017
Tweet

More Decks by Shinichi Kozake

Other Decks in Technology

Transcript

  1. 2TQXKFGTKU !$PNQPOFOU \  QSPWJEFST<)FSP4FSWJDF>   ^  FYQPSUDMBTT)FSPFT$PNQPOFOU\^

    !/H.PEVMF \  QSPWJEFST< 6TFS4FSWJDF  \QSPWJEF"11@$0/'*( VTF7BMVF)&30@%*@$0/'*(^ >   ^  FYQPSUDMBTT"QQ.PEVMF\^ TSDBQQBQQNPEVMFUT TSDBQQIFSPFTIFSPFTDPNQPOFOUUT 鰄鰽 鰄鰽
  2. DMBTT)FMMP4FSWJDF\ IFMMP)FMMPXPSME ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<)FMMP4FSWJDF>

     TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS !*OKFDU )FMMP4FSWJDF QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ BQQDPNQPOFOUUT 5ZQF サービスをコンポーネントにDIする⼀般的な⽅法が上のコードです。 (コンポーネントにサービスのクラスを書くのはѱ⼿ですが、今回は分かりやすさを優先してここに書いています。) コンポーネントデコレータのprovidersにサービス型を定義し、コンストラクタでそのサービスをインジェクトします。
  3. DMBTT)FMMP4FSWJDF\ IFMMP)FMMPXPSME ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF

    VTF$MBTT)FMMP4FSWJDF^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS !*OKFDU )FMMP4FSWJDF QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ BQQDPNQPOFOUUT 5ZQF 先ほどのproviders定義は、上のコード指定と同じです。 providでHelloServiceの型をインジェクショントークンとして指定し、インスタンスはHelloServiceクラスから作成することを 指定しています。 QSPWJEFST<)FMMP4FSWJDF> ⛭鰉秷鯵
  4. DMBTT)FMMP4FSWJDF\ IFMMP)FMMPXPSME ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF

    VTF$MBTT)FMMP4FSWJDF^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS !*OKFDU )FMMP4FSWJDF QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ 5ZQF インジェクショントークンとインジェクトする引਺の型が同じ場合、Injectデコレータによるトークン指定を省略することがで きます。 䧢䡆⛐聚
  5. DMBTT)FMMP4FSWJDF\ IFMMP)FMMPXPSME ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF

    VTF$MBTT)FMMP4FSWJDF^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS !*OKFDU )FMMP4FSWJDF QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ BOZ providには型以外も指定できます。 例えば、’HelloService’という⽂字列を指定することも出དྷます。 㡨⸸⓸鰘稊⹻
  6. DMBTT)FMMP4FSWJDF\IFMMP)FMMPXPSME^ DMBTT%*TVLJ4FSWJDF\IFMMP%*TVLJXPSME^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF VTF$MBTT)FMMP4FSWJDF^

     \QSPWJEF)FMMP4FSWJDF VTF$MBTT%*TVLJ4FSWJDF^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS !*OKFDU )FMMP4FSWJDF QSJWBUFIFMMP)FMMP4FSWJDF  !*OKFDU )FMMP4FSWJDF QSJWBUFIFMMP%*TVLJ4FSWJDF \^ UJUMFA\UIJTIFMMPIFMMP^\UIJTIFMMPIFMMP^A ^ BOZ ただ、⽂字列でインジェクショントークンを指定した場合、同じ⽂字列で別の定義があると、定義が上書きされてしまいます。 複਺プロバイダによるインジェクショントークンの衝突が⼼配です。 上のコードでは、helloม਺にはHelloServiceではなく、DIsukiServiceのインスタンスがインジェクトされてしまいました。 鰚鰒鰺鰳&+UWMK猳
  7. DMBTT)FMMP4FSWJDF\IFMMP)FMMPXPSME^ DMBTT%*TVLJ4FSWJDF\IFMMP%*TVLJXPSME^ DPOTU)FMMP5PLFOOFX0QBRVF5PLFO )FMMP4FSWJDF  DPOTU)FMMP5PLFOOFX0QBRVF5PLFO )FMMP4FSWJDF  !$PNQPOFOU \

    TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP5PLFO VTF$MBTT)FMMP4FSWJDF^  \QSPWJEF)FMMP5PLFO VTF$MBTT%*TVLJ4FSWJDF^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS !*OKFDU )FMMP5PLFO QSJWBUFIFMMP)FMMP4FSWJDF  !*OKFDU )FMMP5PLFO QSJWBUFIFMMP%*TVLJ4FSWJDF \^ UJUMFA\UIJTIFMMPIFMMP^\UIJTIFMMPIFMMP^\)FMMP5PLFO)FMMP5PLFO^A ^ 0QBRVF5PLFO そのような衝突をさけるҝに、⽂字列のトークンではなくOpaqueTokenを⽤います。 OpaqueTokenは同じ⽂字列でも違うものとして認識されます。 *GNNQ6QMGP*GNNQ6QMGP
  8. DMBTT)FMMP4FSWJDF\ IFMMP)FMMPXPSME ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF

    VTF$MBTT)FMMP4FSWJDF^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ VTF$MBTT useClassは値としてクラスを受け取り、Injectのたびにそのクラスのインスタンスを作ります。 Injectのたびにຖ回newです。
  9. DMBTT)FMMP4FSWJDF\IFMMP)FMMPXPSME^ DMBTT%*TVLJ4FSWJDF\IFMMP%*TVLJXPSME^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF VTF$MBTT%*TVLJ4FSWJDF^>

     TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ VTF$MBTT ちなみに、provideで指定したインジェクショントークンと異なる型のクラスを指定することも出དྷます。 ただし、不必要に混ཚを招くため、このような使⽤⽅法は避けたほうがいいでしょう。 䡑鰛鰼⩬猳猳獑
  10. DMBTT)FMMP4FSWJDF\IFMMP)FMMPXPSME^ DMBTT%*TVLJ4FSWJDFFYUFOET)FMMP4FSWJDF\IFMMP%*TVLJXPSME^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF VTF$MBTT%*TVLJ4FSWJDF^>

     TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ VTF$MBTT インジェクショントークンの型をܧ承したクラスをuseClassに指定するなどの使⽤⽅法は、型として互換があるので問題ないと 思います。 ⩬鰙鰈鰗ⅳ稰鯽鯳鰼
  11. DMBTT)FMMP4FSWJDF\ DPOTUSVDUPS QSJWBUFOBNFTUSJOH \^ IFMMPA)FMMP\UIJTOBNF^A ^ MFUIFMMP"OHVMBSOFX)FMMP4FSWJDF "OHVMBS  !$PNQPOFOU

    \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF VTF7BMVFIFMMP"OHVMBS^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ VTF7BMVF useValueは値としてオブジェクトを受け取り、Injectされるたびにそのࢀ照を渡します。 定਺のように使えますが、ࢀ照が渡ってくるのでDIされたオブジェクトをม更すると、別の箇所に影響しますので注意が必要で す。 餿䑈鱃䄂鰊
  12. DMBTT)FMMP4FSWJDF\ DPOTUSVDUPS QSJWBUFOBNFTUSJOH \^ IFMMPA)FMMP\UIJTOBNF^A ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU 

    UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF  VTF'BDUPSZ OFX)FMMP4FSWJDF "OHVMBS ^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ VTF'BDUPSZ useFactoryの値にはؔ਺を渡します。Injectされるたびにؔ਺が࣮⾏され、その໭り値が注⼊されます。 環境によって異なるインスタンスを⽣成したい場合などに、useFactoryを使⽤します。
  13. DMBTT)FMMP4FSWJDF\ DPOTUSVDUPS QSJWBUFOBNFTUSJOH \^ IFMMPA)FMMP\UIJTOBNF^A ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU 

    UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF  VTF'BDUPSZ OFX)FMMP4FSWJDF "OHVMBS ^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ VTF'BDUPSZ @armorik83 さんから勉ڧձでご指摘頂きました。ありがとうございます! exportしていないクラスやアローؔ਺式のFactoryはAoTコンパイルでエラーとなります。 ؾをつけましょう! FYQPSUDMBTT)FMMP4FSWJDF\ DPOTUSVDUPS QSJWBUFOBNFTUSJOH \^ IFMMPA)FMMP\UIJTOBNF^A ^ FYQPSUGVODUJPO)FMMP4FSWJDF'BDUPSZ \ SFUVSOOFX)FMMP4FSWJDF "OHVMBS  ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF  VTF'BDUPSZ)FMMP4FSWJDF'BDUPSZ^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  GZRQTV鰈鰗鯵鰛鯵鱓鲍鱝鰠#Q6鱗鲗鱵鱈鲏鰘鱌鲍鯮 鱆鲑鯮鏈窚ㇰ鰳#Q6鱗鲗鱵鱈鲏鰘鱌鲍鯮 鰄鰟鰹鯷鰜㧙鰀鰙 鱗鲗鱵鱈鲏蒌鰼
  14. DMBTT)FMMP4FSWJDF\ DPOTUSVDUPS QSJWBUFOBNFTUSJOH \^ IFMMPA)FMMP\UIJTOBNF^A ^ DPOTU)FMMP/BNFOFX0QBRVF5PLFO OBNF  !$PNQPOFOU

    \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP/BNF VTF7BMVFOHLZPUP^  \QSPWJEF)FMMP4FSWJDF  VTF'BDUPSZ OBNFTUSJOH OFX)FMMP4FSWJDF OBNF   EFQT<)FMMP/BNF>^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ VTF'BDUPSZ useFactoryを⽤いる場合、depsでインジェクショントークンを指定することが出དྷます。 depsでインジェクショントークンを指定すると、useFactoryのؔ਺にインジェクトした引਺を渡すことが出དྷます。
  15. DMBTT)FMMP4FSWJDF\ DPOTUSVDUPS QSJWBUFOBNFTUSJOH \^ IFMMPA)FMMP\UIJTOBNF^A ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU 

    UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF  VTF'BDUPSZ OFX)FMMP4FSWJDF "OHVMBS ^  \QSPWJEF)FMMP"OHVMBS  VTF&YJTUJOH)FMMP4FSWJDF^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS !*OKFDU )FMMP"OHVMBS QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ VTF&YJTUJOH useExistingは値としてインジェクショントークンをとり、それにରするエイリアスを作ります。 つまり異なるインジェクショントークンで同じインスタンスが得られるようになります。 useClassとはਅ逆で、⼀切newしません。 上のコード例の場合、’HelloAngular’の⽂字列トークンでもHelloServiceのインスタンスを得ることが出དྷています。 ┆痓鱃∽㓱
  16. DMBTT)FMMP4FSWJDF\IFMMP)FMMPXPSME^ DMBTT%*TVLJ4FSWJDF\IFMMP%*TVLJXPSME^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF VTF$MBTT)FMMP4FSWJDF

    NVMUJUSVF^  \QSPWJEF)FMMP4FSWJDF VTF$MBTT%*TVLJ4FSWJDF NVMUJUSVF^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS !*OKFDU )FMMP4FSWJDF QSJWBUFIFMMP\IFMMPTUSJOH^<> \^ UJUMFA\UIJTIFMMP NBQ PPIFMMP SFEVDF N N N  N ^A ^ NVMUJ 通常は同じインジェクショントークンにରして複਺Providerを宣⾔すると、最後に宣⾔されたものに上書きされますが、multiを trueに指定すると、インジェクショントークンにରして複਺のProviderを提供することが出དྷます。 この場合、インジェクトされるม਺の型は配列にします。 苭窚鰛鰟鰘蔥⓸
  17. DMBTT)FMMP4FSWJDF\ IFMMP)FMMPXPSME ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF

    VTF$MBTT)FMMP4FSWJDF^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS  !*OKFDU "OHVMBS4FSWJDF QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPOVMM UIJTIFMMPIFMMPOVMM ^ 0QUJPOBM 依存性解決出དྷなかった場合、DIエラーとなってしまいます。 上のコードの場合、’AngularService’という⽂字列のインジェクショントークンで依存性が解決出དྷなかったので、エラーがൃ ⽣します。 㨋⹻劊鰟鱬鯮鱓鲗
  18. DMBTT)FMMP4FSWJDF\ IFMMP)FMMPXPSME ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<\QSPWJEF)FMMP4FSWJDF

    VTF$MBTT)FMMP4FSWJDF^>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS  !0QUJPOBM !*OKFDU "OHVMBS4FSWJDF QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPOVMM UIJTIFMMPIFMMPOVMM ^ 0QUJPOBM 依存性解決出དྷなかった場合にもエラーにしたくない場合は、Optionalデコレータで指定します。 こうすることで、依存性解決出དྷなかったม਺の値がnullとなるだけで、エラーはൃ⽣しません。 VJKUJGNNQ鰟甧鰠PWNN
  19. DMBTT8IP\OBNF"OHVMBS^ DMBTT)FMMP4FSWJDF\ DPOTUSVDUPS QSJWBUFXIP8IP \^ IFMMPA)FMMP\UIJTXIPOBNF^A ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU

     UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<8IP )FMMP4FSWJDF>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ *OKFDUBCMF サービスもDIにより依存性を解決出དྷますが、上のコードはエラーとなります。 理由としては、Injectorで依存性解決可能なクラスとして認識されていないからです。 鱵鲍鲅鯮鱣鱃茭㽛鰘鯾鰛鯵猳
  20. !*OKFDUBCMF  DMBTT8IP\OBNF"OHVMBS^ !*OKFDUBCMF  DMBTT)FMMP4FSWJDF\ DPOTUSVDUPS QSJWBUFXIP8IP \^ IFMMPA)FMMP\UIJTXIPOBNF^A

    ^ !$PNQPOFOU \ TFMFDUPSBQQSPPU  UFNQMBUF6SMBQQDPNQPOFOUIUNM  QSPWJEFST<8IP )FMMP4FSWJDF>  TUZMF6SMT<BQQDPNQPOFOUDTT> ^  FYQPSUDMBTT"QQ$PNQPOFOU\ DPOTUSVDUPS QSJWBUFIFMMP)FMMP4FSWJDF \^ UJUMFUIJTIFMMPIFMMP ^ *OKFDUBCMF サービスも依存性解決ର象にしたい場合は、Injectableデコレータを指定します。 Angularでは、すべてのサービスにInjectableデコレータを指定するスタイルが推঑されています。 なお、ComponentでInjectableが必要なかった理由は、ComponentやDirective、Pipeは、Injactableのサブタイプだからで す。
  21. *OKFDUPS5SFF ∼Rangle's Angular Training Book [The Injector Tree] よりൈਮ∼ AngularのInjectorはコンポーネントツリーとฒ⾏してツ

    リーを形成します。 Injectorはすべてのコンポーネントຖに作成されるわけでは なく、デコレータでprovidersが指定されたコンポーネント ຖに作成され、Injector Treeを形成します。 コンポーネントは⾃分⾃⾝、もしくは⾃分の親のコンポーネ ントのInjectorをたどることで、依存性解決を解決します。 Injectorຖにインスタンスはシングルトンなので、その⼦コ ンポーネントは親と同じインスタンスをࢀ照します。