Angular 2 Notes - Modules
API Service
- First, configure the application to use server communication facilities.
The Angular Http
client communicates with the server using a familiar HTTP request/response protocol. The Http
client is one of a family of services in the Angular HTTP library.
E.g., main.ts
... |
When importing from the @angular/http module, SystemJS knows how to load services from the Angular HTTP library because the systemjs.config.js file maps to that module name.
JsonpModule isn’t necessary for plain HTTP.
Make a General Service
E.g.,api.ts
import { Injectable } from '@angular/core'; |
In fact, the http.get method returns an Observable of HTTP Responses (Observable
- Export providers
E.g.,../index.ts
import * as services from './services' |
- Export services
E.g.,../services/index.ts
export { ApiService } from './api'; |
Implement a service
E.g.,note.ts
import { Injectable } from '@angular/core'; |
Apply a service
E.g.,notes.ts
import { NoteService } from '../services'; |
This is a best practice. Components are easier to test and debug when their constructors are simple, and all real work (especially calling a remote server) is handled in a separate method.
To listen for events in this stream, subscribe to the Observable (Here, we have translated the obserable to json). These subscriptions specify the actions to take when the web request produces a success event (with the data in the event payload) or a fail event (with the error in the payload).
Promise Based
getHeroes (): Promise<Hero[]> { |
We can follow the promise then(this.extractData).catch(this.handleError)
pattern as in this example.
While promises may be more familiar, observables have many advantages.
Alternatively, you can call toPromise(success, fail)
. The observable’s map callback moves to the first success parameter and its catch callback to the second fail parameter in this pattern: .toPromise(this.extractData
, this.handleError).
Also, We have to adjust the calling component to expect a Promise instead of an observable:getHeroes() {
this.heroService.getHeroes()
.then(
heroes => this.heroes = heroes,
error => this.errorMessage = <any>error);
}
addHero (name: string) {
if (!name) { return; }
this.heroService.addHero(name)
.then(
hero => this.heroes.push(hero),
error => this.errorMessage = <any>error);
}
The less obvious but critical difference is that these two methods return very different results.
The promise-based
then
returns another promise. You can keep chaining morethen
andcatch
calls, getting a new promise each time.
Thesubscribe
method returns aSubscription
. ASubscription
is not anotherObservable
. It’s the end of the line for observables. You can’t call map on it or call subscribe again. TheSubscription
object has a different purpose, signified by its primary method,unsubscribe
.
Observalbe Based*
ConceptObservable
in short addresses asynchronous processing and events. Comparing to promise
, it can be described as observable
= promise
+ events.
What is great with observables
is that they are lazy. Observables
can be canceled and you can apply some operators in them (like map
, filter
, …). This allows to handle asynchronous things in a very flexible way.
A great sample describing the strong power of observables
is the way to connect a filter input to a corresponding filtered list. When the user enters characters, the list is refreshed. Observables
handle corresponding AJAX requests and cancel previous in progress requests if another one is triggered by new value in the input. E.g.,
this.textValue.valueChanges |
In action
- Manage the observable by your own. In this case, call the
subscribe
method on the observable and assign the result into an attribute of the component. Then use this attribute in the view to iterate over the collection:
@Component({ |
Returns from both get and map methods are the observable not the result (in the same way than with promises).
- Manage the observable by the Angular template. You can also use the a pipe to implicitly manage the observable. In this case, there is no need to explicitly call the subscribe method.
@Component({ |
Note that observables are lazy. So the corresponding HTTP request will be only called once when a listener attached on it is using the subscribe method.
The map
method is used to extract the JSON content from the response and use it in the observable processing.
State Management
Make a Store
e.g., store.ts
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Injectable } from '@angular/core';
import 'rxjs/Rx';
export interface Note {
color: string,
title: string,
value: string,
id?: string | number,
createdAt?: string,
updatedAt?: string,
userId?: string
}
export interface State {
notes: Array<Note>
}
const defaultState : State = {
notes: []
}
const _store = new BehaviorSubject<State>(defaultState);
@Injectable()
export class Store {
private _store = _store;
changes = this._store.asObservable().distinctUntilChanged()
setState(state: State) {
this._store.next(state);
}
getState(): State {
return this._store.value;
}
purge() {
this._store.next(defaultState);
}
}
Make a Store-Helper
e.g., store-helper.ts
import { Injectable } from '@angular/core'; |
Implement a Store
In container note.ts
,
import { Store } from '../store'; |
In service note.ts
, keep the store up-to-date.
import { StoreHelper } from './store-helper'; |
Ref: