Making Angular Service – Always  Singleton

By default, Angular Services are Singleton. When you create a service using the CLI command,

ng g s App

Angular creates a service named AppService.

import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AppService {
constructor() { }
}
view raw serviceex.js hosted with ❤ by GitHub

The above service is

  1. Singleton
  2. Tree-shakeable
  3. Available throughout the application

Singleton means Angular creates only one object of the AppService, regardless of how many places you use it. However, if you re-provide the service in another component or a module and use it inside, Angular will create separate objects for them.

As shown below , if you again provide the AppService in ProductComponent; Angular creates a new object of the AppService, and provides it to the ProductComponent and all its child components.

@Component({
selector: 'app-fipq',
templateUrl: './fipq.component.html',
styleUrls: ['./fipq.component.css'],
providers: [AppService]
})
export class ProductComponent implements OnInit {
constructor(private appservice: AppService) { }
ngOnInit(): void {
}
}

Sometimes you may have a requirement to prevent a service from being instantiated more than once. As you have seen that if you re-provide a service, Angular creates a new object of that. You can prevent this, as shown.

To prevent a service to be re provided and getting more than one objects being created,  you can create a injector guard.

import { inject, InjectOptions, Type } from "@angular/core";
export class RootInjectorGuard {
option: InjectOptions = {
skipSelf: true,
optional: true
};
constructor(type: Type<any>) {
console.log(type.name);
const parent = inject(type, this.option);
if (parent) {
throw Error(`[${type.name}]: Can not create more than one instance`);
}
}
}

After creating injector, modify the service as shown below.

import { Injectable } from '@angular/core';
import { RootInjectorGuard } from './root-injector.guard';
@Injectable({
providedIn: 'root'
})
export class AppService extends RootInjectorGuard {
constructor() {
super(AppService)
}
getData(){
return "data";
}
}

Basically, to make a service singleton, extends the guard and in the constructor of the service, pass the service class to the guard.

Now when you re-provide the AppService, Angular will throw you error, as shown below

I hope you find this post useful and now should be able to use it in your project and answer in interview.  Thanks for reading.


Discover more from Dhananjay Kumar

Subscribe to get the latest posts sent to your email.

Published by Dhananjay Kumar

Dhananjay Kumar is founder of NomadCoder and ng-India

Leave a comment

Discover more from Dhananjay Kumar

Subscribe now to keep reading and get access to the full archive.

Continue reading