Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mistake in Angular document for providing Singleton Services #30941

Closed
CodingYiyi opened this issue Jun 10, 2019 · 10 comments
Closed

Mistake in Angular document for providing Singleton Services #30941

CodingYiyi opened this issue Jun 10, 2019 · 10 comments

Comments

@CodingYiyi
Copy link

CodingYiyi commented Jun 10, 2019

📚 Docs or angular.io bug report

Description

As below:
"If a module defines both providers and declarations (components, directives, pipes), then loading the module in multiple feature modules would duplicate the registration of the service. This could result in multiple service instances and the service would no longer behave as a singleton."
Q1:Must be met “defines both providers and declarations” ?
i have tried it and can't understand is there any relationship with “declarations” prop?
Q2:The mentioned in the content 'feature modules' means lazy loading modules?

🔬 Minimal Reproduction

Declare a shared module(without 'declarations' prop, only 'providers' prop) and loading the module in two lazy loading modules

What's the affected URL?**

https://angular.io/guide/singleton-services#the-forroot-pattern

Reproduction Steps**

Expected vs Actual Behavior**

I just can not understand the below content:
"If a module defines both providers and declarations", <-- is this a must required condition?

📷Screenshot

🔥 Exception or Error





🌍 Your Environment

Browser info

Anything else relevant?

@FrederikSchlemmer
Copy link
Contributor

@kapunahelewong seems like there is also a problem with the note in this chapter. I tried to take a view on the NgModules live example from the note.
The example results in a 'PAGE NOT FOUND'-Error.

@CodingYiyi
Copy link
Author

updated the affected URL

@FrederikSchlemmer
Copy link
Contributor

@kapunahelewong seems like there is also a problem with the note in this chapter. I tried to take a view on the NgModules live example from the note.
The example results in a 'PAGE NOT FOUND'-Error.

Seems like live-examples\ngmodules\stackblitz.html would be the suitable live example.

@CodingYiyi If I unterstood the documentation corretly the feature modules doesn't have to be lazy loaded. They can be basic feature modules without lazy loading.

If you take a look in the linked example of the NgModules there is a example with the GreetingModule. You can see the amount of registrated services, when using forRoot() in the AppModule. Without using forRoot() multiple service instances are created.

Correct me if I'm wrong!

Maybe @kapunahelewong the example should be mentioned in the chapter for better understanding. Would you suggest any other changes? I would like apply them!

@kapunahelewong
Copy link
Contributor

Thanks for your help, @FrederikSchlemmer 🌼and for pointing out the broken link. I've submitted a PR for it. Good catch!

@CodingYiyi These are great questions. I'm working on making sure I have accurate answers for you. Ultimately, this has to do with injector trees (my favorite topic, really!), so please know I haven't forgotten your question but am working on finding the answers and sorting out the nuances so I can explain it properly and edit the doc because you're right, that could use clarification. Thanks for bringing this up - I will come back with more info! 🌈

@kapunahelewong kapunahelewong added this to Pending - Top of backlog in docs Aug 6, 2019
@kapunahelewong
Copy link
Contributor

Hi @CodingYiyi, thanks for your patience on this. I've interviewed a few people to try to help you on this. The answer to your first question:

Q1:Must be met “defines both providers and declarations” ?

No, they are independent of each other.

The next one is actually nuanced and I had to think about it once the kind @robwormald explained it to me.

Q2:The mentioned in the content 'feature modules' means lazy loading modules?

Generally, yes, but because we normally create child modules/injectors by lazy loading. Feature modules are automatically created as child modules/injectors with something like childModuleFactory.create(parentInjector), which is exactly what the router does when lazy loading.

A point of interest is that the ModuleInjectors are flattened into one ModuleInjector when everything is imported up front. However, if you're providing a service after init, it has to be providedIn or belong to another NgModule. If it belongs to an NgModule, you can only instantiate that module as a child. The fact that they are lazy-loaded isn’t a requirement, it’s more that the fact they’re lazy loaded means that they are being created after init.

So services are either:

  1. providedIn, and can be inserted into an injector at any time. That is, services can be inserted after init if they are providedIn, but modules can not, and thus must be a child.

  2. Or services belong to a module, are created in the child injector, and are only visible at that level. In plain terms this all means if you want to lazily provide a singleton service, it should be provdedIn: root.

Note that tree shakable (providedIn: root in @Injectable()) can be inserted into an already existing injector because tree shakable services don't belong to a module - you say, "hey, provide this in myModule".

Additionally, I have a PR #28700 that's hopefully close to being merged all about the underlying reasons for some of the questions this issue brings up. Here's a preview of the doc https://pr28700-40830de.ngbuilds.io/guide/hierarchical-dependency-injection that's easier to read than the PR diff.

@CodingYiyi, please let me know your thoughts and if you have any more questions. I'm happy to help find answers for you.

@CodingYiyi
Copy link
Author

@kapunahelewong I'm sorry to have interval for so long after my last comment, and appreciate for your reply, I have read your explanation carefully, and came to some conclusions as below:

1.if a service is provided in a component using @component ({providers:[]}), then it's not singleton service.
2.we can use either
@Injectable({providedIn:'root'})
or
Include the service in the AppModule or in a module that is only imported by the AppModule
to create a singleton service.
3.if we include a service (eg. testService) in both AModule and BModule using providers prop, and import both A,BModule into AppModule, the testService is singleton, and available throughout the whole app(include CModule) .
4.Include the service in a lazy load module using providers prop can also create a singleton service, but can only be used in this lazy load module, not available in the other module.

Correct me if I'm wrong.

@kapunahelewong
Copy link
Contributor

Hi @CodingYiyi! It's ok, your timing is just right. 🌼And yes, you're correct - you've explained it perfectly. Now that you have that concept clear, you might also be interested in the resolution modifiers because they help you customize this behavior. https://angular.io/guide/hierarchical-dependency-injection

If you take a look at them and have questions, please let me know. We rewrote that relatively recently and if there are any points that need clarifying I'm especially interested in doing so.

@kapunahelewong kapunahelewong moved this from Pending - Top of backlog to Committed - Selected for development in docs Nov 27, 2019
@rockument69
Copy link
Member

Hi @kapunahelewong, do we need more engineering input for this? Or is it already fixed, or have a PR awaiting something? Thanks.

@kapunahelewong
Copy link
Contributor

@CodingYiyi I'm closing this issue because I think your issue is resolved. If you still have any questions please feel free to re-open and tag me. Thank you!

@jbogarthyde jbogarthyde removed this from Committed - Selected for development in docs Jun 10, 2020
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jun 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants