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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s