Ang2

Angular 2 Services

Learn how to create reusable functionality within a service that components can access via dependency injection.

Up to date (Aug '17) Angular 2

Services allow for greater seperation of concerns for your application and better modularity by allowing you to extract common functionality out of components. Angular also comes with its own dependency injection framework for resolving dependencies, so you can have your services depend on other services throughout your application, and dependency injection will resolve your dependencies for you.

Dependency Hierarchy

Each instance of component has an injector, and when a dependency is requested it looks at its own injector to see if it has the dependency. If it doesn't, it will look at its parent component's injector, until it reaches the root component of your app. The injectors are responsible for instantiating the services and keeping track of them for child components to use. This behavior is slightly different from dependency injection in Angular 1.x, where the injector tree was flat and were tied to individual modules.

Services need to be registered in the providers array at the parent-most component that will be using it. There will one instance of your service per injector, so registering a service more than once can cause your app to have multiple instances of the same service in your child components.

It's also worth noting that not all services are singletons. They can be if you register them in the AppModule that's used for bootstrapping, but there may be cases where you want to register a service at a child-level component, where each instance of that component gets their own instance of the service.

The @Injectable Decorator

The @Injectable() decorator is needed when a Service needs dependencies injected to its constructor. Although it is optional when a service doesn't need dependencies injected into it, a common practice is to use the Injectable() decorator for all services for consistency and so that when a service requires dependencies in the future you don't have to worry about remembering to add the decorator.

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

@Injectable() // The Injectable decorator is required for dependency injection to work
export class RepoService{
  constructor(private http: Http){
  }

  fetchAll(){
    return this.http.get('https://api.github.com/repositories').map(res => res.json());
  }
}
import { Injectable } from '@angular/core';

@Injectable() // Injectable is optional because this service doesn't have any dependencies
export class RepoService{
  constructor(){
  }

  fetchAll(){
    return [
      {
        id: 1,
        name: 'grit'
      },
      {
        id: 26,
        name: 'merb-core'
      }
    ];
  }
}

Make sure that the parenthesis are present when using the @Injectable() decorator. Using @Injectable won't properly apply the decorator to your service.

Additional Reading

Dependency Injection Guide

Dependency Injection Overview

Hierarchical Dependency Injection Guide

 

I finished! On to the next chapter