Apr 11, 2017

Angular - Observables

Observables is an ES7 feature which means you need to make use of an external library to use it today. RxJS is a good one. This is not angular 2 specific feature, though angular cli does add this to the dependencies. Observables gives you all the features of promises and more. A Promise handles a single event when an async operation completes or fails, whereas Observable is like a Stream and allows to pass zero or more events where the callback is called for each event. For example FormControl valueChanges returns Observable, so I can write a code like this which will write to console every time value is changed.
   
   let sub =  this.name.valueChanges.pipe(debounceTime(1000))subscribe(
      (newValue: string) => {
       console.log(newValue);
       if (newValue.length === 5) {
        sub.unsubscribe();
       }
      });

In the following example we are making an http call and I am expecting number, then I apply pipe, which gives me option to transform data before passing to the subscriber. This will be helpful if I would like to transform data before sending to subscriber or may be convert error to standard format. Keep in mind observable are deferred execution, so unless it has a subscriber it (along with operators in pipes) will not be executed
   import { Observable, BehaviorSubject, throwError, combineLatest, forkJoin } from 'rxjs';
   import { retry, catchError, tap, map, filter, finalize,  delay,debounceTime } from 'rxjs/operators';
   import { HttpClient } from '@angular/common/http'; 

   this.http.get(url).pipe(
        retry(3),
        map(obj=>{return obj *2;}),
        tap(obj => {console.log(obj)}),
        catchError((err)=>{return throwError(err);})
      ).subscribe(
        (value)=>{console.log(value)},
        (err)=>{console.log(err)},
        ()=>{console.log('done')}
      );

combineLatest
once all input observables have produced at least one value it returns Observable and after that it returns Observable everytime it produces a new value.
forkJoin
It require all the observables to be completed and then returns single value that is an array of the last values produced by the input observables

Observable also has the advantage over Promise to be cancelable. One of the example will be for type ahead, if user has changed the text which will result in new http call, we can cancel subscription to the previous one. In case of promise, the callback call will happen either in success or failure scenario. Promises doesn't have option of Lazy loading where as observable will not be executed until someone subscribe to it. You also have option on retry and retryWhen in observable.
If you subscribe to an observable or event in JavaScript, you should unsubscribe at a certain point to release memory in the system, otherwise it will lead to memory leak. Here are few of the case where you should explicitly unsubscribe
1. Form value change as shown in the example above
2. Router to be on safe side, though angular claim to clean it up.
3. Infinite observable
 Observable.interval(1000).subscribe(console.log(''))
 Observable.fromEvent(this.element.nativeElement, 'click').subscribe(console.log('hi'));
For the following case you don't need to unsubscribe
1. aysnc pipe - When the component gets destroyed, the async pipe unsubscribes automatically.
2. Finite Observable - When you have a finite sequence, usually you don’t need to unsubscribe, for example when using the HTTP service or the timer observable

No comments:

Post a Comment