|  | 
|  | 1 | +# Singleton services | 
|  | 2 | + | 
|  | 3 | +A singleton service is a service for which only one instance exists in an app. | 
|  | 4 | + | 
|  | 5 | +For a sample app using the app-wide singleton service that this page describes, see the | 
|  | 6 | +<live-example name="ngmodules"></live-example> showcasing all the documented features of NgModules. | 
|  | 7 | + | 
|  | 8 | +## Providing a singleton service | 
|  | 9 | + | 
|  | 10 | +There are two ways to make a service a singleton in Angular: | 
|  | 11 | + | 
|  | 12 | +* Set the `providedIn` property of the `@Injectable()` to `"root"`. | 
|  | 13 | +* Include the service in the `AppModule` or in a module that is only imported by the `AppModule` | 
|  | 14 | + | 
|  | 15 | + | 
|  | 16 | +{@a providedIn} | 
|  | 17 | + | 
|  | 18 | +### Using `providedIn` | 
|  | 19 | + | 
|  | 20 | +Beginning with Angular 6.0, the preferred way to create a singleton service is to set `providedIn` to `root` on the service's `@Injectable()` decorator. This tells Angular | 
|  | 21 | +to provide the service in the application root. | 
|  | 22 | + | 
|  | 23 | +<code-example path="providers/src/app/user.service.0.ts"  header="src/app/user.service.ts"></code-example> | 
|  | 24 | + | 
|  | 25 | +For more detailed information on services, see the [Services](tutorial/toh-pt4) chapter of the | 
|  | 26 | +[Tour of Heroes tutorial](tutorial). | 
|  | 27 | + | 
|  | 28 | +### NgModule `providers` array | 
|  | 29 | + | 
|  | 30 | +In apps built with Angular versions prior to 6.0, services are registered NgModule `providers` arrays as follows: | 
|  | 31 | + | 
|  | 32 | +```ts | 
|  | 33 | +@NgModule({ | 
|  | 34 | +  ... | 
|  | 35 | +  providers: [UserService], | 
|  | 36 | +  ... | 
|  | 37 | +}) | 
|  | 38 | + | 
|  | 39 | +``` | 
|  | 40 | + | 
|  | 41 | +If this NgModule were the root `AppModule`, the `UserService` would be a singleton and available | 
|  | 42 | +throughout the app. Though you may see it coded this way, using the `providedIn` property of the `@Injectable()` decorator on the service itself is preferable as of Angular 6.0 as it makes your services tree-shakable. | 
|  | 43 | + | 
|  | 44 | +{@a forRoot} | 
|  | 45 | + | 
|  | 46 | +## The `forRoot()` pattern | 
|  | 47 | + | 
|  | 48 | +Generally, you'll only need `providedIn` for providing services and `forRoot()`/`forChild()` for routing. However, understanding how `forRoot()` works to make sure a service is a singleton will inform your development at a deeper level. | 
|  | 49 | + | 
|  | 50 | +If a module defines both providers and declarations (components, directives, pipes), | 
|  | 51 | +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. | 
|  | 52 | + | 
|  | 53 | +There are multiple ways to prevent this: | 
|  | 54 | + | 
|  | 55 | +* Use the [`providedIn` syntax](guide/singleton-services#providedIn) instead of registering the service in the module. | 
|  | 56 | +* Separate your services into their own module. | 
|  | 57 | +* Define `forRoot()` and `forChild()` methods in the module. | 
|  | 58 | + | 
|  | 59 | +<div class="alert is-helpful"> | 
|  | 60 | + | 
|  | 61 | +**Note:** There are two example apps where you can see this scenario; the more advanced <live-example noDownload name="ngmodules">NgModules live example</live-example>, which contains `forRoot()` and `forChild()` in the routing modules and the `GreetingModule`, and the simpler <live-example name="lazy-loading-ngmodules" noDownload>Lazy Loading live example</live-example>. For an introductory explanation see the [Lazy Loading Feature Modules](guide/lazy-loading-ngmodules) guide. | 
|  | 62 | + | 
|  | 63 | +</div> | 
|  | 64 | + | 
|  | 65 | + | 
|  | 66 | +Use `forRoot()` to | 
|  | 67 | +separate providers from a module so you can import that module into the root module | 
|  | 68 | +with `providers` and child modules without `providers`. | 
|  | 69 | + | 
|  | 70 | +1. Create a static method `forRoot()` on the module. | 
|  | 71 | +2. Place the providers into the `forRoot()` method. | 
|  | 72 | + | 
|  | 73 | +<code-example path="ngmodules/src/app/greeting/greeting.module.ts" region="for-root" header="src/app/greeting/greeting.module.ts"></code-example> | 
|  | 74 | + | 
|  | 75 | + | 
|  | 76 | +{@a forRoot-router} | 
|  | 77 | + | 
|  | 78 | +### `forRoot()` and the `Router` | 
|  | 79 | + | 
|  | 80 | +`RouterModule` provides the `Router` service, as well as router directives, such as `RouterOutlet` and `routerLink`. The root application module imports `RouterModule` so that the application has a `Router` and the root application components can access the router directives. Any feature modules must also import `RouterModule` so that their components can place router directives into their templates. | 
|  | 81 | + | 
|  | 82 | +If the `RouterModule` didn’t have `forRoot()` then each feature module would instantiate a new `Router` instance, which would break the application as there can only be one `Router`. By using the `forRoot()` method, the root application module imports `RouterModule.forRoot(...)` and gets a `Router`, and all feature modules import `RouterModule.forChild(...)` which does not instantiate another `Router`. | 
|  | 83 | + | 
|  | 84 | +<div class="alert is-helpful"> | 
|  | 85 | + | 
|  | 86 | +**Note:** If you have a module which has both providers and declarations, | 
|  | 87 | +you _can_ use this | 
|  | 88 | +technique to separate them out and you may see this pattern in legacy apps. | 
|  | 89 | +However, since Angular 6.0, the best practice for providing services is with the | 
|  | 90 | +`@Injectable()` `providedIn` property. | 
|  | 91 | + | 
|  | 92 | +</div> | 
|  | 93 | + | 
|  | 94 | +### How `forRoot()` works | 
|  | 95 | + | 
|  | 96 | +`forRoot()` takes a service configuration object and returns a | 
|  | 97 | +[ModuleWithProviders](api/core/ModuleWithProviders), which is | 
|  | 98 | +a simple object with the following properties: | 
|  | 99 | + | 
|  | 100 | +* `ngModule`: in this example, the `GreetingModule` class | 
|  | 101 | +* `providers`: the configured providers | 
|  | 102 | + | 
|  | 103 | +In the <live-example name="ngmodules">live example</live-example> | 
|  | 104 | +the root `AppModule` imports the `GreetingModule` and adds the | 
|  | 105 | +`providers` to the `AppModule` providers. Specifically, | 
|  | 106 | +Angular accumulates all imported providers | 
|  | 107 | +before appending the items listed in `@NgModule.providers`. | 
|  | 108 | +This sequence ensures that whatever you add explicitly to | 
|  | 109 | +the `AppModule` providers takes precedence over the providers | 
|  | 110 | +of imported modules. | 
|  | 111 | + | 
|  | 112 | +The sample app imports `GreetingModule` and uses its `forRoot()` method one time, in `AppModule`. Registering it once like this prevents multiple instances. | 
|  | 113 | + | 
|  | 114 | +You can also add a `forRoot()` method in the `GreetingModule` that configures | 
|  | 115 | +the greeting `UserService`. | 
|  | 116 | + | 
|  | 117 | +In the following example, the optional, injected `UserServiceConfig` | 
|  | 118 | +extends the greeting `UserService`. If a `UserServiceConfig` exists, the `UserService` sets the user name from that config. | 
|  | 119 | + | 
|  | 120 | +<code-example path="ngmodules/src/app/greeting/user.service.ts" region="ctor" header="src/app/greeting/user.service.ts (constructor)"></code-example> | 
|  | 121 | + | 
|  | 122 | +Here's `forRoot()` that takes a `UserServiceConfig` object: | 
|  | 123 | + | 
|  | 124 | +<code-example path="ngmodules/src/app/greeting/greeting.module.ts" region="for-root" header="src/app/greeting/greeting.module.ts (forRoot)"></code-example> | 
|  | 125 | + | 
|  | 126 | +Lastly, call it within the `imports` list of the `AppModule`. In the following | 
|  | 127 | +snippet, other parts of the file are left out. For the complete file, see the <live-example name="ngmodules"></live-example>, or continue to the next section of this document. | 
|  | 128 | + | 
|  | 129 | +<code-example path="ngmodules/src/app/app.module.ts" region="import-for-root" header="src/app/app.module.ts (imports)"></code-example> | 
|  | 130 | + | 
|  | 131 | +The app displays "Miss Marple" as the user instead of the default "Sherlock Holmes". | 
|  | 132 | + | 
|  | 133 | +Remember to import `GreetingModule` as a Javascript import at the top of the file and don't add it to more than one `@NgModule` `imports` list. | 
|  | 134 | + | 
|  | 135 | +## Prevent reimport of the `GreetingModule` | 
|  | 136 | + | 
|  | 137 | +Only the root `AppModule` should import the `GreetingModule`. If a | 
|  | 138 | +lazy-loaded module imports it too, the app can generate | 
|  | 139 | +[multiple instances](guide/ngmodule-faq#q-why-bad) of a service. | 
|  | 140 | + | 
|  | 141 | +To guard against a lazy loaded module re-importing `GreetingModule`, add the following `GreetingModule` constructor. | 
|  | 142 | + | 
|  | 143 | +<code-example path="ngmodules/src/app/greeting/greeting.module.ts" region="ctor" header="src/app/greeting/greeting.module.ts"></code-example> | 
|  | 144 | + | 
|  | 145 | +The constructor tells Angular to inject the `GreetingModule` into itself. | 
|  | 146 | +The injection would be circular if Angular looked for | 
|  | 147 | +`GreetingModule` in the _current_ injector, but the `@SkipSelf()` | 
|  | 148 | +decorator means "look for `GreetingModule` in an ancestor | 
|  | 149 | +injector, above me in the injector hierarchy." | 
|  | 150 | + | 
|  | 151 | +By default, the injector throws an error when it can't | 
|  | 152 | +find a requested provider. | 
|  | 153 | +The `@Optional()` decorator means not finding the service is OK. | 
|  | 154 | +The injector returns `null`, the `parentModule` parameter is null, | 
|  | 155 | +and the constructor concludes uneventfully. | 
|  | 156 | + | 
|  | 157 | +It's a different story if you improperly import `GreetingModule` into a lazy loaded module such as `CustomersModule`. | 
|  | 158 | + | 
|  | 159 | +Angular creates a lazy loaded module with its own injector, | 
|  | 160 | +a child of the root injector. | 
|  | 161 | +`@SkipSelf()` causes Angular to look for a `GreetingModule` in the parent injector, which this time is the root injector. | 
|  | 162 | +Of course it finds the instance imported by the root `AppModule`. | 
|  | 163 | +Now `parentModule` exists and the constructor throws the error. | 
|  | 164 | + | 
|  | 165 | +Here are the two files in their entirety for reference: | 
|  | 166 | + | 
|  | 167 | +<code-tabs> | 
|  | 168 | + <code-pane header="app.module.ts" path="ngmodules/src/app/app.module.ts"> | 
|  | 169 | + </code-pane> | 
|  | 170 | + <code-pane header="greeting.module.ts" region="whole-greeting-module" path="ngmodules/src/app/greeting/greeting.module.ts"> | 
|  | 171 | + </code-pane> | 
|  | 172 | +</code-tabs> | 
|  | 173 | + | 
|  | 174 | +<hr /> | 
|  | 175 | + | 
|  | 176 | +## More on NgModules | 
|  | 177 | + | 
|  | 178 | +You may also be interested in: | 
|  | 179 | +* [Sharing Modules](guide/sharing-ngmodules), which elaborates on the concepts covered on this page. | 
|  | 180 | +* [Lazy Loading Modules](guide/lazy-loading-ngmodules). | 
|  | 181 | +* [NgModule FAQ](guide/ngmodule-faq). | 
0 commit comments