Thursday, April 13, 2017

Observables in Angular

Observables are the bread and butter Angular (2+).  Thus, it is good to take some time to learn how to use them.  Trust me.  They look a little more complicated than promises and callbacks, but it will speed up development if you add these to your toolkit.



Observables?


Observables are the basic building block for many of the things in the RxJS library.  What it essentially boils down to is a continuous stream of values sent from an emitter to a listener.  Observables help you define how the data is received, mapped, and emitted to these listeners called observers. 

Observables are kind of like a more powerful Promise, and observers are the things that execute after the “.then()”.

Why use it?


The two main differences between observables and promises are the ability to tear down and only calling methods when there is a subscriber.  Additionally, certain observers can unsubscribe or stop listening to the observable.  These two things don’t necessarily sound that important, but they have very large practical effects.

For a simple one off http call, it is simpler to write a promise to handle the data output and call .then() to catch it and handle it.  The problem is when use cases get more and more complicated, then promises stop working as intended.  Race conditions start appearing, followed by memory leaks. 

Lazy requests


This meant that if you do not call .subscribe() in your class or | async in the html then the observable will not fire.  If you are new to observables, this will undoubtedly trip you up and give you some heartache.  However, it is a neat feature that allows you to modify your code so that you can removed and add observers.  When you have none, then your http calls aren’t firing. 

Remember that if you have multiple observers, then you should apply .share() to your observables, or the function will run multiple times.

Asynchronous calls


Http now uses observables by default instead of promises like in AngularJS.  For the most part the code looks similar.

In AngularJS,

//in service
function httpCall() {
return $http.get(url);
}
//in controller
function doSomething() {
            service.httpCall().then(
function(data){//do something with data},
function(err){//error handling}
);
}

In Angular
//service
function httpCall() {
return this.http.get(url)
.catch(//error handling function);
}
//in component
function doSomething() {
            service.httpCall().subscribe(res=> {
                        //do something with data
            });
}

However, we gain to use observable operators directly on our response object, and we can pass in an interface for type checking on our observables to use elsewhere in our code.

If we add another type of Observable called Subject, then we can effectively manage which http call will be shown to the user. 

private subject = new Subject<any>();
this.entries = this.subject
      .switchMap((data) => {
            //if data is not empty switch to a new doSomething Observable, else empty observable
        return data ? this.service.doSomething(data): Observable.of<Type[]>([])})
      .catch(error => {
//empty observable
        return Observable.of<Type[]>([]);
      });

In this use case, we call the same api endpoint with http requests, but we provide different parameters to it based on user input.  This allows us to call .next(//latest user input) on subject, which in turns will deconstruct observables for old http request.  This is most useful for searches such as google instant, where a new http request is spawned every letter.  It also gives us the freedom to apply restrictions on how often these calls will be made, such as a 100ms delay or waiting for unique input.

Other uses


Observables can be used for form validation, emitting data between components, and a lot of other things other than async calls.  There is a whole slew of methods that allow you to manipulate the data and reorganize it to your heart’s desire.  It is also more maintainable. 

If anything is unclear, then leave a comment.  I probably didn’t do the best job of explaining it.


Peter

No comments:

Post a Comment