Singleton Service In Angular

Singleton Service In Angular

A singleton service is one in which there is only one instance in an app. In this article, We will learn how to establish a singleton service in Angular when it's in the root module, eagerly loaded module, or lazy loaded module.

How to Create a Singleton Service in Angular

A Singleton Service can be created in one of two methods.

Using the providedIn property's root option. Regardless of whether your service is in an eager or lazy loaded module, this works. The providedIn method is recommended since it allows the service tree to be shaken.

@Injectable({ 
  providedIn: 'root' 
})
export class AppService {
...
}

The second way is to include it in the @NgModule Providers array.

If the NgModule is a root or eagerly loaded module, the AppService is exposed to the entire application as a Singleton service.

However, if the NgModule is a lazy-loaded module, AppService is only available within that module and not elsewhere.
@NgModule({
  imports: [],
  declarations: [],
  bootstrap: [],
  providers: [AppService]     <===
})
export class AppModule {}

Angular Singleton Service Example

The app is divided into three sections. AppModule, EagerModule, and LazyModule are three types of modules.

A random generation service is available in all modules. AppService, LazyService, and EagerService are three different types of services. The AppService's code can be found below. The code for both the LazyService and the EagerService is the same. To distinguish it from other services, we simply prefixed the random number with the service name.

Open the app.service.ts file and put the following code
import { Injectable } from '@angular/core';
 
@Injectable()
export class AppService {
  private _randomNo = '';
 
  constructor() {
    console.log('AppService Constructed');
    this._randomNo = 'App ' + Math.floor(Math.random() * 1000 + 1);
  }
 
  get RandomNo() {
    return this._randomNo;
  }
}

There are four parts to our system. The Root Module's AppComponent and HelloComponent, EagerModule's EagerComponent, and LazyModule's LazyComponent

The HelloComponent's code is as follows.

Now, Open the hello.component.ts file and put the folloeing code
import { Component, Input, Optional } from '@angular/core';
import { AppService } from './app.service';
import { EagerService } from './eager/eager.service';
import { LazyService } from './lazy/lazy.service';
 
@Component({
  selector: 'hello',
  providers:[],
  template: `
    Hello Works {{ randomApp }} {{ randomEager }} {{ randomLazy }}
  `,
  styles: [
    `
      h1 {
        font-family: Lato;
      }
    `
  ]
})
export class HelloComponent {
  randomApp = 'App : Not defined';
  randomEager = 'Eager : Not defined';
  randomLazy = 'Lazy : Not defined';
 
  constructor(
    @Optional() private appService: AppService,
    @Optional() private eagerService: EagerService,
    @Optional() private laztyService: LazyService
  ) {
    if (appService) this.randomApp = this.appService.RandomNo;
    if (eagerService) this.randomEager = this.eagerService.RandomNo;
    if (laztyService) this.randomLazy = this.laztyService.RandomNo;
  }
 
  ngOnInit() {}
}

All three services have been injected into HelloComponent. If the service is not available, the Optional Decorator guarantees that Angular returns null rather than issuing an exception.
constructor(
  @Optional() private appService: AppService,
  @Optional() private eagerService: EagerService,
  @Optional() private laztyService: LazyService
)

All of the other components have codes that are comparable. A navigation menu is available in the AppComponent.

We begin by eliminating the providedIn parameter and emptying the provider's array. This will result in all of the components' displays being set to Not defined. Because we're using the optional decorator, no errors are thrown.

Service in the root module

The root module contains the AppService.

Add it to the @NgModul of the AppModule's Providers array.
@NgModule({
  imports: [BrowserModule,FormsModule,RouterModule.forRoot(routes),EagerModule],
  declarations: [AppComponent, HelloComponent],
  bootstrap: [AppComponent],
  providers: [AppService]
})
export class AppModule {}

For the Random No., you can see that all components have the same value (including those from EagerModule & LazyModule ). The AppService Constructed can only be seen once in the console.

Another option is to use the providedIn: 'root' decorator in the AppService's @Injectable decorator.
@Injectable({ providedIn: 'root' })
export class AppService {

Service in the eagerly loaded module

In the same way as in the root module, the services in the eagerly loaded module can be made singletons.

With the @Injectable decorator, you can include it in the providedIn:'root'.
@Injectable({ providedIn: 'root' })
export class EagerService {

Alternatively, add it to the providers array of the EagerModule's NgModule decorator.
@NgModule({
  imports: [CommonModule, RouterModule.forChild(routes)],
  declarations: [EagerComponent],
  providers: [EagerService]
})
export class EagerModule {}

Service in the lazy loaded module

Adding the LazyService to the LazyModule's providers array. However, the LazyService is only available within the LazyModule and not elsewhere.
@NgModule({
  imports: [CommonModule, RouterModule.forChild(routes)],
  declarations: [LazyComponent],
  providers: [LazyService]
})
export class LazyModule {}

The only way to do so is to use the providedIn: 'root' in the LazyService's Injectable.
@Injectable({ providedIn: 'root' })
export class LazyService {

Conclusion

In this article, We covered how to establish a singleton service in Angular when it's in the root module, eagerly loaded module, or lazy loaded module.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in comment section.

Post a Comment

Previous Post Next Post