Myślę, że odpowiedzi są prawidłowe, ale myślę, że czegoś brakuje.
To, czego brakuje, to „dlaczego i co rozwiązuje?”.
Ok zaczynajmy.
Najpierw wspomnijmy o kilku informacjach:
Wszystkie moduły mają dostęp do usług root.
Więc nawet leniwie ładowane moduły mogą korzystać z usługi dostarczonej w app.module
.
Co się stanie, jeśli leniwie ładowany moduł zapewni sobie usługę, którą dostarczył już moduł aplikacji? będą 2 wystąpienia.
To nie jest problem, ale czasami jest .
Jak możemy to rozwiązać? po prostu nie importuj modułu z tym dostawcą do modułów ładowanych z opóźnieniem.
Koniec opowieści.
To ^ miało tylko pokazać, że moduły ładowane z opóźnieniem mają swój własny punkt wstrzykiwania (w przeciwieństwie do modułów ładowanych z opóźnieniem).
Ale co się stanie, gdy udostępniony (!) Moduł zadeklaruje providers
, a ten moduł zostanie zaimportowany przez lazy i app.module
? Znowu, jak powiedzieliśmy, dwa przypadki.
Jak więc możemy rozwiązać ten problem we współdzielonym module POV? Potrzebujemy sposobu, aby nie używać providers:[]
! Czemu? ponieważ zostaną one automatycznie zaimportowane zarówno do zużywającego lazy, jak i do modułu app.module, a nie chcemy tego, ponieważ widzieliśmy, że każdy będzie miał inną instancję.
Cóż, okazuje się, że możemy zadeklarować współdzielony moduł, który nie będzie miał providers:[]
, ale nadal będzie dostarczał dostawców (przepraszam :))
W jaki sposób? Lubię to :
Uwaga, brak dostawców.
Ale
co się stanie teraz, gdy app.module zaimportuje udostępniony moduł z punktem widzenia usługi? NIC.
co się stanie teraz, gdy leniwy moduł zaimportuje moduł współdzielony z POV usługi? NIC.
Wchodzenie do mechanizmu ręcznego poprzez konwencję:
Zauważysz, że dostawcy na zdjęciach mają service1
iservice2
To pozwala nam na importowanie service2
dla leniwie ładowanych modułów i service1
dla nieleniwych modułów. ( kaszel ... router ... kaszel )
BTW, nikt nie powstrzymuje Cię przed wywołaniem forRoot
w leniwym module. ale będziesz mieć 2 instancje, ponieważ app.module
też powinieneś to robić - więc nie rób tego w leniwych modułach.
Ponadto - jeśli app.module
wywołuje forRoot
(i nikt nie dzwoni forchild
) - w porządku, ale iniektor root będzie miał tylko service1
. (dostępne dla wszystkich aplikacji)
Dlaczego więc tego potrzebujemy? Powiedziałbym :
Pozwala modułowi współdzielonemu, aby móc podzielić jego różnych dostawców w celu użycia ich z chętnymi modułami i leniwymi modułami - za pośrednictwem forRoot
i forChild
konwencji. Powtarzam: konwencja
Otóż to.
CZEKAJ !! ani słowa o singletonie ?? więc dlaczego wszędzie czytam singletona?
Cóż - jest to ukryte w zdaniu powyżej ^
Pozwala modułowi współdzielonemu, aby móc podzielić jego różnych dostawców w celu użycia z modułami chętnymi i leniwymi - za pośrednictwem forRoot i forChild .
Konwencja (!!!) pozwala to być pojedyncza - albo dokładniej - jeśli nie będą postępować zgodnie z konwencją - będziesz NIE dostać pojedyncza.
Więc jeśli załadować tylko forRoot
w app.module
, a następnie dostać tylko jedną instancję, bo tylko powinien wezwać forRoot
go w app.module
.
Swoją drogą - w tym miejscu można o tym zapomnieć forChild
. leniwie ładowany moduł nie powinien / nie dzwoni forRoot
- więc jesteś bezpieczny w POV singletona.
forRoot i forChild to nie jeden nierozerwalny pakiet - po prostu nie ma sensu wywoływać Roota, który oczywiście będzie ładowany tylko app.module
bez możliwości leniwych modułów, ma własne usługi, bez tworzenia nowych usług-które-powinny-być -singel.
Konwencja ta daje fajną możliwość zwaną forChild
- konsumować "usługi tylko dla leniwie ładowanych modułów".
Oto wersja demonstracyjna Dostawcy root zwracają liczby dodatnie, moduły ładowane z opóźnieniem dają liczby ujemne.