- Observables are another way of handling async tasks. Angular2 use them a lot.
- Usually are objects wrapping some data source which emits events, such as button clicks , https requests, etc.
Analyzing a Built in observable
- We already used observables when subscribing to changes int the route params:
this.route.params.subscribe( (params: Params)=> { this.id = +params['id']; this.editMode = !isNaN(this.id); } );
Building and using a first simple Observable
- We will make a observable which print a number in the console every second.
- This is a built-in utility in rxjs package
... import { Observable } from 'rxjs/Observable'; import 'rxjs/Rx'; ... ngOnInit() { const myNumbers = Observable.interval(1000); myNumbers.subscribe( (number: number) => { console.log(number); } ); }
Building and using a custom observable from scratch
- Let make a custom observable which prints to console after 2 seconds , 4 seconds and complete on five seconds.
const myObservable = Observable.create((observer: Observer<string>) => { setTimeout(()=> { observer.next('first package'); },2000); setTimeout(()=> { observer.next('second package'); },4000); // setTimeout(()=> { // observer.error('error ocurred!'); // },5000); setTimeout(()=> { observer.complete(); },5000); setTimeout(()=> { observer.next('third package'); },6000); }); myObservable.subscribe( (data:string)=> { console.log(data); }, (error:string)=> { console.log(error); }, ()=> { console.log('completed'); }, );
NOTE: third package is not printed because it is emitted after observable is completed (dead).
Unsubscribe!
- We must not forget clean up our subscriptions on leaving the component. Otherwise we could lead to a memory leak. We will do it in the destroy lifecycle method.
... subscription1: Subscription; subscription2: Subscription; ... this.subscription1 = myNumbers.subscribe( (number: number) => { console.log(number); } ); this.subscription2 = myObservable.subscribe( (data:string)=> { console.log(data); }, (error:string)=> { console.log(error); }, ()=> { console.log('completed'); }, ); ... ngOnDestroy() { this.subscription1.unsubscribe(); this.subscription2.unsubscribe(); } ...
Where to learn more
Using Subject to pass and listen to data
- Subject is a object from Rxjs package that is Observable and Observer at the same instance.
- It is very useful in cross component communication instead of emit events
user.service.ts
import {Subject} from 'rxjs/Subject'; ... export class UsersService { userActivated = new Subject(); ...
app.component.html
<hr> <h4>Using Subjects (from RxJs)</h4> <p> User is {{userActivated? '(activated)':''}} <button (click)="onActivate()">Activate user</button> </p>
app.component.ts
... userActivated = false; constructor( private usersService: UsersService , ... ngOnInit() { this.subscription3 = this.usersService.userActivated.subscribe( (text: string)=> { if(text) { this.userActivated = true; } }); ... onActivate() { this.usersService.userActivated.next('dfdfdfd'); }
Understanding observable operators
- Observable operators return observables , so you can chain them.
- In http://reactivex.io/rxjs/ , in the Observable object you can check all operators available.
- Lets make an example using map operator to print double numbers in the console
const myNumbers = Observable.interval(1000).map( (data:number)=>{ return data*2; } );
ds
ds
ds
d
sd