FrontEndTech
  • Introduction
  • ReactJS
    • Ecosystem
    • Refactor Using Functional Decomposition and Reducer Composition
  • AngularJS
    • installation
    • File structure
    • CLI
      • ng g
    • Fundamentals
      • Component
        • Lifecycle
        • Template
      • Decorations
      • Service
      • Pipe
      • Directives
        • NgClass
        • NgStyle
        • NgModel
        • Customized Attribute Directives
        • NgIf
        • NgFor
        • NgSwitch
        • NgForm
        • Customized Structural Directives
      • Module
        • Routing
    • Bindings
      • Property Binding
      • Event Binding
      • Data Binding
      • Attribute Binding
      • Class Binding
      • Style Binding
    • Forms
      • Reactive Form
      • Reactive vs Template
    • build
Powered by GitBook
On this page
  • Distinguishes Components from Services
  • Injector
  • Why do we need Service
  • Provide the Service
  • Where to Inject & call Service
  • Inject
  • call
  • How to Call: Synchronous v.s Asynchronous

Was this helpful?

  1. AngularJS
  2. Fundamentals

Service

Service is a broad category encompassing any value, function, or feature that an app needs.

For data or logic that is not associated with a specific view, and that you want to share across components, you create a service class.

A service class definition is immediately preceded by the @Injectable decorator.

The decorator provides the metadata that allows your service to be injected into client components as a dependency.

Distinguishes Components from Services

component's job

  • enable the user experience and nothing more

  • present properties and methods for data binding, in order to mediate between the view (rendered by the template) and the application logic (which often includes some notion of a model).

not component's job (can delegate such tasks to services)

  • define how to fetch data from the server

  • validate user input

  • log directly to the console

By defining that kind of processing task in an injectable service class, you make it available to any component.

You can also make your app more adaptable by injecting different providers of the same kind of service, as appropriate in different circumstances.

Injector

Angular creates an application-wide injector for you during the bootstrap process.

The injector maintains a container of dependency instances that it has already created, and reuses them if possible.

For any dependency you need in your app, you must register a provider with the app's injector, so that the injector can use it to create new instances.

When Angular creates a new instance of a component class, it determines which services or other dependencies that component needs by looking at the types of its constructor parameters.

For example, the constructor of HeroListComponent needs a HeroService:

constructor(private service: HeroService) { }

When Angular discovers that a component depends on a service, it first checks if the injector already has any existing instances of that service. If a requested service instance does not yet exist, the injector makes one using the registered provider, and adds it to the injector before returning the service to Angular.

Why do we need Service

Components shouldn't fetch or save data directly and they certainly shouldn't knowingly present fake data. They should focus on presenting data and delegate data access to a service.

Services are a great way to share information among classes that don't know each other.

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

@Injectable()
export class HeroService {

  constructor() { }

}

The @Injectable() decorator tells Angular that this service might itself have injected dependencies.

Provide the Service

You must provide the HeroService in the dependency injection system before Angular can inject it into the HeroesComponent

There are several ways to provide the HeroService: in the HeroesComponent, in the AppComponent, in the AppModule. Each option has pros and cons.

src/app/app.module.ts (providers)

providers: [
    HeroService,
/* . . . */
  ],

The providers array tells Angular to create a single, shared instance of HeroService and inject into any class that asks for it.

Where to Inject & call Service

Inject

Angular will inject the singleton MessageService into that property when it creates the HeroService.

constructor(public messageService: MessageService) {}

Reserve the constructor for simple initialization such as wiring constructor parameters to properties. The constructor shouldn't do anything. It certainly shouldn't call a function that makes HTTP requests to a remote server as a real data service would.

call

ngOnInit() {
  this.getHeroes();
}

How to Call: Synchronous v.s Asynchronous

The HeroService.getHeroes() method has a synchronous signature, which implies that the HeroService can fetch heroes synchronously.

this.heroes = this.heroService.getHeroes();

This will not work in a real app. The assignment occurs synchronously, as if the server could return heroes instantly or the browser could freeze the UI while it waited for the server's response.

You're getting away with it now because the service currently returns mock heroes. But soon the app will fetch heroes from a remote server, which is an inherently asynchronous operation.

HeroService.getHeroes() must have an asynchronous signature of some kind. It can take a callback. It could return a Promise. It could return an Observable.

import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';

getHeroes(): Observable<Hero[]> {
  return of(HEROES);
}

In the HTTP tutorial, you'll call HttpClient.get<Hero[]>() which also returns an Observable<Hero[]> that emits a single value, an array of heroes from the body of the HTTP response.

getHeroes(): void {
  this.heroService.getHeroes()
      .subscribe(heroes => this.heroes = heroes);
}
PreviousDecorationsNextPipe

Last updated 5 years ago

Was this helpful?