Acho que as respostas estão certas, mas acho que falta algo.
O que falta é "por que e o que isso resolve?".
OK vamos começar.
Primeiro, vamos mencionar algumas informações:
Todos os módulos têm acesso aos serviços raiz.
Assim, mesmo os módulos carregados lentamente podem usar um serviço que foi fornecido em app.module
.
O que acontecerá se um módulo de carregamento lento fornecer a si mesmo um serviço que o módulo de aplicativo já forneceu? haverá 2 instâncias.
Não é um problema, mas às vezes é .
Como podemos resolver isso ? simplesmente não importe um módulo com esse provedor para módulos carregados lentamente.
Fim da história.
Este ^ era apenas para mostrar que os módulos carregados lentamente têm seu próprio ponto de injeção (em oposição aos módulos carregados não lentamente).
Mas o que acontece quando um módulo compartilhado (!) É declarado providers
e esse módulo é importado por lazy e app.module
? Novamente, como dissemos, duas instâncias.
Então, como podemos resolver isso no módulo POV compartilhado? Precisamos de uma maneira de não usar providers:[]
! Por quê? porque eles serão importados automaticamente para consumir lazy e app.module e não queremos isso, pois vimos que cada um terá uma instância diferente.
Bem, acontece que podemos declarar um módulo compartilhado que não terá providers:[]
, mas ainda fornecerá provedores (desculpe :))
Quão? Como isso :
Observe, nenhum provedor.
Mas
o que acontecerá agora quando app.module importará o módulo compartilhado com POV de serviço? NADA.
o que acontecerá agora quando um módulo preguiçoso importará o módulo compartilhado com POV de serviço? NADA.
Entrando no mecanismo manual via convenção:
Você notará que os provedores nas fotos têm service1
eservice2
Isso nos permite importar service2
módulos carregados lentamente e módulos service1
não lazy. ( tosse ... roteador .... tosse )
BTW, ninguém está impedindo você de ligar forRoot
em um módulo preguiçoso. mas você terá 2 instâncias porque app.module
também deve fazê-lo - portanto , não o faça em módulos preguiçosos.
Além disso - se app.module
ligar forRoot
(e ninguém ligar forchild
) - tudo bem, mas o injetor root só terá service1
. (disponível para todos os aplicativos)
Então, por que precisamos disso? Eu diria :
Ele permite que um módulo compartilhado seja capaz de dividir seus diferentes provedores para serem usados com módulos ávidos e módulos lazy - via forRoot
e forChild
convenção. Repito: convenção
É isso aí.
ESPERAR !! nem uma única palavra sobre singleton ?? então por que eu leio singleton em todos os lugares?
Bem - está escondido na frase acima ^
Ele permite que um módulo compartilhado seja capaz de dividir seus diferentes provedores para serem usados com módulos ávidos e módulos lazy - via forRoot e forChild .
A convenção (!!!) permite que seja um singleton - ou para ser mais preciso - se você não seguir a convenção - você NÃO receberá um singleton.
Portanto, se você carregar apenas forRoot
no app.module
, obterá apenas uma instância, pois só deve chamá- forRoot
la no app.module
.
BTW - neste ponto você pode esquecer forChild
. o módulo de carregamento lento não deve / não chama forRoot
- então você está seguro no POV do singleton.
forRoot e forChild não são um pacote inquebrável - é só que não adianta chamar o Root que obviamente será carregado apenas app.module
sem dar a capacidade de módulos preguiçosos, ter seus próprios serviços, sem criar novos serviços que deveriam ser -singleton.
Esta convenção oferece uma boa capacidade chamada forChild
- para consumir "serviços apenas para módulos carregados lentamente".
Aqui está uma demonstração que os provedores de raiz geram números positivos, os módulos carregados lentamente geram números negativos.