Home Angular Tutorials How to use Angular Singleton Service ?

How to use Angular Singleton Service ?

by aouidane.med.amine
174,391 views 10 min read

Welcome to this tutorial on singleton services in Angular!

In this tutorial, you will learn what singleton services are, how to create and use them in your Angular applications, and when to use them.

Table of Contents

What is Singleton Service in Angular ?

Angular singleton service is a service that is instantiated only once and shared among all components in the application.

This means that all components in the application that inject the same singleton service will receive the same instance of the service.

Angular Singleton services are useful for storing and sharing application-wide data and logic, such as user authentication or application settings.

They can also be used to avoid unnecessary service instantiations, which can improve the performance of your application.

How to create Singleton Service in Angular ?

There are two main ways to create a singleton service in Angular:

  • Using providedIn property 

 You can use the providedIn property of the @Injectable decorator to specify that the service should be provided in the root injector or in a specific module.

This will create a singleton service that is available to all components in the application or in a specific module, depending on how you configure the providedIn property.

Here is an example of a singleton service provided in the root injector:

				
					import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class MyService {
  // service methods and properties go here
}

				
			

And here is an example of a singleton service provided in a specific module:

				
					import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'myModule'
})
export class MyService {
  // service methods and properties go here
}

				
			

 

  • Using a provider in a module 

Another way to create an angular singleton service is to use a provider in a module.

You can do this by adding a provider to the providers array of the @NgModule decorator. This will create a singleton service that is available to all components in the module.

Here is an example of a singleton service provided using a provider in a module:

				
					import { NgModule } from '@angular/core';
import { MyService } from './my.service';

@NgModule({
  providers: [MyService]
})
export class MyModule { }

				
			

In this example, the MyService service will be available to all components in the MyModule module.

Angular Singleton Service Example

Here is a basic example of a singleton service in Angular that stores and retrieves a user’s name:

				
					import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private userName: string;

  constructor() { }

  setUserName(name: string) {
    this.userName = name;
  }

  getUserName(): string {
    return this.userName;
  }
}

				
			

To use this service in a component, you can inject it into the component’s constructor and use its methods to set and retrieve the user’s name:

				
					import { UserService } from './user.service';

@Component({
  // component metadata goes here
})
export class MyComponent {
  constructor(private userService: UserService) { }

  setUserName(name: string) {
    this.userService.setUserName(name);
  }

  getUserName(): string {
    return this.userService.getUserName();
  }
}

				
			

In this example, the UserService is a singleton service that is shared among all components in the application, and all components that inject the UserService will receive the same instance of the service.

This means that any component can use the setUserName and getUserName methods to set and retrieve the user’s name, and the value will be the same for all components.

Singleton Service in Lazy Loaded Module

You cannot use both approaches (using provideIn property & using provider in module) to create a singleton service in a lazy-loaded module.

If you use the providedIn property in the service to specify that the service should be provided at the root level, it will be available throughout the application, including in the lazy-loaded module.

				
					@Injectable({ providedIn: 'root' })
export class myService { 
//your lazy service
}
				
			

However, if you provide the service in the lazy-loaded module using the providers array in the @NgModule decorator, the service will only be available in the lazy-loaded module and not outside of it.

				
					@NgModule({
  imports: [],
  declarations: [myComponent],
  providers: [myService]
})
export class LazyModule {}
				
			

In this case, the service will not be a singleton service and a new instance will be created for each component that uses it.

To create a singleton service that is available throughout the application, including in the lazy-loaded module, you should provide the service at the root level using the providedIn property or the providers array in the root module.

 

  • Using Factory to prevent problems ( use case )

There can be a problem with using a singleton service in a lazy-loaded module if the service needs to perform some initialization that requires the module to be loaded first.

For example, let’s say you have a service that needs to load some data from a remote API when it is initialized.

If you provide the service at the root level, it will be initialized as soon as the application starts, even before the lazy-loaded module is loaded.

This can cause problems if the service needs to wait for the lazy-loaded module to be loaded before it can initialize itself.

To solve this problem, you can use a factory function to create the service instance when the lazy-loaded module is actually loaded.

This way, you can ensure that the service is initialized only when the module is loaded, and the initialization can depend on the module being present.

Here is an example of how you can use a factory function to create a singleton service in a lazy-loaded module:

				
					import { NgModule, Injector } from '@angular/core';
import { MyComponent } from './my.component';
import { MyService } from './my.service';

export function createMyService(injector: Injector) {
  return new MyService(injector);
}

@NgModule({
  declarations: [MyComponent],
  providers: [
    {
      provide: MyService,
      useFactory: createMyService,
      deps: [Injector]
    }
  ]
})
export class MyLazyLoadedModule { }

				
			

This way, the MyService will be a singleton service that is shared by all components in the application, including those in the lazy-loaded module.

The service will be initialized only when the lazy-loaded module is actually loaded, and the initialization can depend on the module being present.

References and Links

You may also like