Using providedIn
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 to provide the service in the application root.
src/app/user.service.ts
content_copy
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class UserService {
}
For more detailed information on services, see the Services chapter of the Tour of Heroes tutorial.
NgModule providers array
In apps built with Angular versions prior to 6.0, services are registered NgModule providers arrays as follows:
@NgModule({
...
providers: [UserService],
...
})
If this NgModule were the root AppModule, the UserService would be a singleton and available 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.
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.
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.
There are multiple ways to prevent this:
Use the providedIn syntax instead of registering the service in the module.
Separate your services into their own module.
Define forRoot() and forChild() methods in the module.