Demystifying Angular Services and Dependency Injection
Tags: angular, angularservice, dependencyinjection, typescript
Published: 2022-04-16 06:19:29

---
title: Demystifying Angular Services and Dependency Injection
published: true
date: 2022-04-15 00:00:00 UTC
tags: angular,angularservice, dependencyinjection, typescript
canonical_url: https://yeshasmp.github.io/posts/angular-services/
---

In any Angular application it is essential to keep component as lean as possible, it’s only concern should be on how to present the model data to view as described by [Angular official docs](https://angular.io/guide/architecture-services).

> “a component’s job is to enable the user experience and nothing more.”

where other logics such as fetching data from API endpoint or handling client and server side errors should be taken care by services.

## Angular Services

Angular services are simple class which is used to perform specific functions. Angular Services offer several advantages -

1. It’s easier to write logic once in service and share the service among the components instead of writing the same logic in every component.
2. It’s easier to test and debug.
3. It’s easier maintain and perform code updates when required.

### Angular Service Example

We can generate Angular Service in Angular CLI using `ng g s AppService` where ‘g’ and ’s' is shorthand form for ‘generate service’.

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

@Injectable({
  providedIn: 'root'
})

export class AppService {
  constructor() { }
  alertMsg(msg : string) {
      alert(msg);
  }
}

```

Above service has method to launch alert popup with custom message. `AppComponent` can request `AppService` in it’s constructor and call the alertMsg method as shown below.

```
import { Component } from '@angular/core';
import { AppService } from '../app.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  constructor(private appService:AppService){
      this.appService.alertMsg("App Component launched");
  }
}
}

```

By default, Angular services are singleton. When services are registered either in provider array of root module or with providedIn value of ‘root’ or ‘any’ in the service itself there’s only single instance of service available throughout the application.

We understood how Angular service could be called in any component, but did you wonder how did `AppComponent` got an instance of `AppService`? For any class to execute another class method it needs to create an object of that class and call the method through it unless it’s static. But where did `AppComponent` create any instance of `AppService`?

Let’s move into next section to know how `AppComponent` got an instance of `AppService`.

## Dependency Injection

When `AppComponent` get’s loaded, Angular would create and provide an instance of `AppService` to the `AppComponent` giving access to `alertMsg` method. This process is known as `Dependency Injection`. As stated in [Wikipedia](https://en.wikipedia.org/wiki/Dependency_injection)

> “In software engineering, dependency injection is a technique in which an object receives other objects that it depends on, called dependencies.”

In Angular terms it’s “Responsibility of Angular framework to create an instance of service and provide it to the requested component”. The requested component need not know how and where to create service instance, it can simply request in it’s constructor and Angular would provide it.

Services needs to register itself as dependency before any component can request it. There are 3 ways where service can register itself as dependency -

1) Using providedIn property inside the `@Injectable` decorator of the service class itself. This is preferred way of registering a service as stated by Angular Docs since it tree shakable meaning Angular would include this service during build time if and only any component requests it. Otherwise this is excluded from the build which helps in improving the performance of our app.

```
@Injectable({
  providedIn: 'root'
})

```

2) By registering in provider array at Module level, Component level or Directive level. Service provided like below is not tree shakable and would be included in the build even if no component requests it.

```
providers: [AppService]

```

3) By manually registering using `@Inject` inside constructor of consumer.

```
constructor(@Inject(AppService) private appService)

```

A `Provider` is an object which holds list of all services registered in provider array. Angular creates provider and injector instance for root module and for each lazy loaded module. It also creates injector instance for all components and directives. Each `Injector` holds the provider list of all dependencies registered at respective component, directive or modules.

Note - Angular doesn’t create injector instance for `Eagerly Loaded modules` therefore, the services registered at those modules will be configured in `Root Module injector`.

Typical service when registered in provider array at module or component would look like below -

```
provders : [AppService]

```

which is shorthand property when expanded would look like

```
providers : [{ provide : AppService , useClass : AppService }]

```

`provide` property holds the injection token while `provider` property holds the instruction on how to create the dependency. Injection token can either be a type, a string or an injection token itself. We can not only provide class as dependency but also provide direct value or value returned from function or function itself using `useValue`, `useFactory` and `useExisting` provider properties. Visit [Angular Docs](https://angular.io/guide/dependency-injection-providers) to know more how you use other provider types.

Now let’s breakdown how Angular would resolve the dependency using provider and injector in below steps for better understanding -

![Hierarchical Injection](https://yeshasmp.github.io/images/hierarchical-tree-flowchart.jpg#center)

1. At runtime, Angular resolves dependency by following hierarchical injection tree. An injection tree is nothing but tree of injector instances.

2. By default, Angular creates `Module Injector tree` having one root module injector and seperate module injector for each lazy loaded module. At the top of root module injector sits Null and Platform module injectors. It also creates an `Element Injector tree` which holds injectors of all components and directives.

3. When `AppComponent` requests `AppService` Angular DI system at first will look at the provider array of `AppComponent` using the injection token given in the constructor.

4. If no provider is found in the `AppComponent` injector, then it traverse upto the parent components in search of matching provider using token until it reaches the root component injector in `Element Injector tree`.

5. If no providers are found in `Element Injector tree` then it searches in `Module Injector tree`. If the requested component is under lazy loaded module it searches in the provider of `Lazy Loaded Module injector` before proceeding to the `Root Module injector`.

6. When provider is found, it creates an instance of service and provide it to the requested component. If no provider is found in both `Element Injector` and `Module Injector` trees it reaches Null injector and throws `NullInjectorError` as shown below.

![Angular service null injector error](https://yeshasmp.github.io/images/null-error.jpg#center)

We can control the dependency resolution using @Skip, @SkipSelf, @Optional and @Host resolution modifiers. We can avoid the above null injector error when dependency is tagged with `@Optional` modifier in the requested `AppComponent` constructor like below. Then Angular would return null instead of throwing error.

```
constructor(@Optional private appService : AppService)

```

## Are Angular Services singleton?

Let’s consider below code scenario to understand Hierarchical injection of services and whether Angular services are singleton or not. Head to [Stackblitz](https://stackblitz.com/edit/angular-ivy-r6cden) to experiment and play below code example.

We will create an `AppService` which generates random number when it’s instance is created and return that value through method. Initially we will register `AppService` only in root module using `providedIn` value as ‘root’ -

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

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

  sharedValue : number;

  constructor() { 
    this.sharedValue = Math.floor(Math.random() * 5);
    console.info("AppService instance has been created!")
  }

  getSharedValue(){
    return this.sharedValue;
  }
}

```

Let’s create two more components - `AppComponent` and `HomeComponent` a child of `AppComponent` and request the `AppService` in both the component constrcutor.

`AppComponent` -

```
import { Component } from '@angular/core';
import { AppService } from './app.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  appServiceValue : any;

  constructor(private appService : AppService) { 
    this.appServiceValue = this.appService.getRandomNumber();
  }
}

```

`HomeComponent` -

```
import { Component, OnInit } from '@angular/core';
import { AppService } from '../app.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
  //providers: [AppService]
})
export class HomeComponent {

  appServiceValue : any;

  constructor(private appService : AppService) { 
    this.appServiceValue = this.appService.getRandomNumber();
  }

}

```

We will then display the random number in both app and home component by calling getRandomNumber method and passing the value to view. When we load the application we can see both components get the same random number as they both received same single instance of `AppService` from `Root Module injector`. This proves Angular services are singleton when they are registered only in `Root Module provider`.

![Angular singleton service](https://yeshasmp.github.io/images/singleton.jpg#center)

Now let’s register `AppService` also in `HomeComponent` provider and run the app. App and Home component displays two different random numbers because they both received two different instances of `AppService`. Thus we can say Angular services are not singleton when they are provided at different levels.

![Angular non-singleton service](https://yeshasmp.github.io/images/non-singleton.jpg#center)

But how did two instance of Angular services got created?

![Angular Hierarchical Injection](https://yeshasmp.github.io/images/hierarchical-injection-tree.jpg#center)

1. When `AppComponent` requested the `AppService`, Angular looked for it in `AppComponent` provider at first, when it couldn’t find it it went into `Module injector tree` and found the `AppService` in `Root Module provider` and returned it to `AppComponent`.

2. Next when `HomeComponent` requested `AppService` it found it in the `HomeComponent` provider itself and returned new `AppService` instance to `HomeComponent`.

3. Therefore we saw two instance of `AppService` being created and provided to respective components.

Few points to remember before we conclude -

1. `Element Injector tree` always gets preference over `Module Injector tree` and it is not child of `Module Injector tree`.

2. Angular DI resolves dependencies using bottom to top approach, it starts the search for provider first from the requesting component and then traverse upto the parent components to the `Root Module provider`.

3. Service which are provided at `Root Module` or `Eagerly Loaded Module` are app scoped and accesible to all the components or directives. Services which are provided in `Lazy Loaded Module` are module scoped and available only to the components or directives under that module.

4. `Proivder` holds the list of dependencies with it’s matching token, while `Injector` holds provider itself.

5. If two `Eagerly Loaded modules` providers has service for same injector token then the module which is imported at last in `Root Module` gets preference.

Above code example have been shared over [Github](https://github.com/yeshasmp/AngularService) and [Stackblitz](https://stackblitz.com/edit/angular-ivy-r6cden).

That’s it folks! I hope this article helped you understand better how Angular Dependency works and how Angular Services are singleton by nature.

Stay tuned for more such interesting articles!