If you have been following the development efforts of the Angular2 project, you have witnessed certain highs and lows - but it has been a fun ride. The latest version is only a Release Candidate and the team is getting closer to the final release. I’m really looking forward to that! I wanted to take a moment to highlight (IMO) one of the key services of Angular2 the <inlinecode>http<inlinecode> service.
As a developer you would have to use both the <inlinecode>ng.IHttpService<inlinecode> and the <inlinecode>ng.IQService<inlinecode> in combination to collaborate the deferral of the HTTP request and the promise that represented it. Consider the following:
In this example, we can easily see the interaction betwixt the <inlinecode>ng.IHttpService ($http)<inlinecode> and <inlinecode>ng.IQService ($q)<inlinecode> services. The <inlinecode>$q<inlinecode> variable exposes a <inlinecode>.defer<inlinecode> function that returns a deferred object.
Resolved yielding the materialized value of type <inlinecode>T<inlinecode>
Rejected with the given reason
The deferred object instance is passed into the fluent API’s of the <inlinecode>$http's .success<inlinecode> and <inlinecode>.error<inlinecode> functions accordingly. This pattern works great, but is very limiting and repetitive. You end up writing a lot of boilerplate code and that isn’t very DRY. Let’s look at how this is approached with Angular2’s <inlinecode>http<inlinecode> service using the observable pattern from RxJS!
To be fair, let’s implement the same functionality and public surface-area such that our example services are equivalent.
I am hoping that you noticed how much cleaner this code is, as well as how much more readable!
Now, I know what you’re thinking...these cannot possibly be the same examples, but they are in fact doing the same thing. Dependency Injection (DI) in Angular2 is a lot less error prone (no more magic strings) and way easier than it was in AngularJs 1. Simply do what you’d expect from any other common constructor-based DI framework, ensure that your desired <inlinecode>Http<inlinecode> type is registered as a provider to the system. This happens by way of the <inlinecode>HTTP_PROVIDERS<inlinecode> defined in as part of our bootstrapping of the app.component. More on that in another post. With modern <inlinecode>TypeScript<inlinecode> we can define properties and fields, and their corresponding access modifiers right from within our constructors.
This exemplifies the comparisons in syntax between a simple constructor and the more verbose constructor.
Likewise, the following is true regarding public access modifiers.
Instead of the <inlinecode>.success<inlinecode> invocation with a corresponding <inlinecode>deferred.resolve<inlinecode> call, we now utilize the RxJS <inlinecode>.map<inlinecode> and <inlinecode>.subscribe<inlinecode> operators. Let’s look at these below:>
Transform the items emitted by an Observable by applying a function to each item
The Subscribe operator is the glue that connects an observer to an Observable
Mapping is easy and we can leverage some of the <inlinecode>TypeScript<inlinecode> language features to cast the JSON blobs returned from our services as strongly typed objects. The map operator is actually synonymous with the select operator, so if you’re more familiar with that terminology you can use it interchangeably.
Now that we have an understanding of how RxJS compares to the legacy pattern, we can take advantage of all the various benefits. Imagine with me that we have a need to implement retry logic, this would have been challenging with the legacy pattern but with the new pattern it’s as simple as saying <inlinecode>.retry<inlinecode>. Consider the following:
Now imagine a scenario where a user is typing and you want to provide an autocomplete, you could use <inlinecode>.debounce<inlinecode> to pause for a brief moment prior to sending the request. Likewise, we could apply a .filter that only takes action when a certain number of characters have been entered. Finally, we might utilize <inlinecode>.distinctUntilChanged<inlinecode> to only execute the request once the values are actually different than they once were.
You could take advantage of <inlinecode>.buffer<inlinecode>, <inlinecode>.throttle<inlinecode>, <inlinecode>.interval<inlinecode>, <inlinecode>.window<inlinecode>, <inlinecode>.range<inlinecode>, etc… The list goes on and on, and this is the source for most of what you can take advantage.
Angular2 has a new implementation of their http service that relies on RxJS. The API uses observables and the observer pattern to allow for a fluent experience that is rich and robust. Getting started is straight-forward and simple. Before too long you’ll be taking advantage of the feature-full set of Reactive Extensions and thinking in terms of data streams. This mindset will make your life easier – trust me!