Let us start day 8 of the "Learning Angular 4.0 in 10 Days" series. In the previous articles, we discussed dependency injection and the concept of service in Angular 4.0. If you want to read the previous articles of this series, do visit the below links.
Angular 4.0 introduces many innovative concepts like performance improvements, the Component Routing, sharpened Dependency Injection (DI), lazy loading, async templating, mobile development with Native Script; all linked with a solid tooling and excellent testing support. Making HTTP requests in Angular 4.0 apps looks somewhat different than what we're used to from Angular 1.x, a key difference being that Angular 4's Http returns observables.
It is very clear to us that Angular 4.0 always looks and feels different than the Angular 1.x. In the case of HTTP API calls, the same scenario occurs. The $HTTP service which Angular 1.x provides us works very nicely in most cases. Angular 4.0 HTTP requires that we need to learn some new concept or mechanism, including how to work with observables.
Reactive Extensions for JavaScript (RxJS) is a reactive streams library that allows you to work with Observables. RxJS combines Observables, Operators, and Schedulers so we can subscribe to streams and react to changes using composable operations.
Differences between Angular 1.x $http and Angular 2 Http
Angular 4's HTTP API calling again provides a fairly straightforward way of handling requests. For starters, HTTP calls in Angular 4 by default return observables through RxJS, whereas $http in Angular 1.x returns promises. Using observable streams gives us the benefit of greater flexibility when it comes to handling the responses coming from HTTP requests. For example, we have the potential of tapping into useful RxJS operators like retry so that a failed HTTP request is automatically re-sent, which is useful for cases where users have poor or intermittent network communication.
In Angular 4, HTTP is accessed as an injectable class from angular4/HTTP and, just like other classes, we import it when we want to use it in our components. Angular 4 also comes with a set of injectable providers for HTTP, which are imported via HTTP_PROVIDERS. With these, we get providers such as RequestOptions and response options, which allow us to modify requests and responses by extending the base class for each. In Angular 1.x, we would do this by providing a transformRequest or transformResponse function to our $httpoptions.
Observables vs Promises
When used with HTTP, both implementations provide an easy API for handling requests, but there are some key differences that make Observables a superior alternative,
- Promises only accept one value unless we compose multiple promises (Eg: $q.all).
- Promises can’t be canceled.
We already discussed that in Angular 4.0, there are many new features introduced in Angular 4.0. An exciting new feature used with Angular is the Observable. This isn't an Angular specific feature, but rather a proposed standard for managing async data that will be included in the release of ES7. Observables open up a continuous channel of communication in which multiple values of data can be emitted over time. From this, we get a pattern of dealing with data by using array-like operations to parse, modify and maintain data. Angular uses observables extensively - you'll see them in the HTTP service and the event system.
In version 4.0, Angular mainly introduces reactive programming concepts based on the observables for dealing with the asynchronous processing of data. In angular 1.x, we basically used promises to handle the asynchronous processing. But still, in Angular 4.0, we can still use the promises for the same purpose. The main concept of reactive programming is the observable element which related to the entity that can be observed. Basically, at a normal look, promises and observables seem very similar to each other. Both of them allow us to execute asynchronous processing, register callbacks for both successful and error responses and also notify or inform us when the result is there.
How to define Observables
Before going to details example of observables, first, we need to understand how to define an observables objects. To create an observable, we can use the create method of the Observable object. A function must be provided as a parameter with the code to initialize the observable processing. A function can be returned by this function to cancel the observable.
- var observable = Observable.create((observer) => {
- setTimeout(() => {
- observer.next('some event');
- }, 500);
- });
Similar to promises, observables can produce several notifications using the different methods from the observer:
- next – Emit an event. This can be called several times.
- error – Throw an error. This can be called once and will break the stream. This means that the error callback will be immediately called and no more events or completion can be received.
- complete – Mark the observable as completed. After this, no more events or errors will be handled and provided to corresponding callbacks.
Observables allow us to register callbacks for previously described notifications. The subscribe method tackles this issue. It accepts three callbacks as parameters,
- The onNext callback that will be called when an event is triggered.
- The onError callback that will be called when an error is thrown.
- The onCompleted callback that will be called when the observable completes.
Observable specificities
Observables and promises have many similarities. In spite of that, observables provide us some new specifications like below,
- Lazy
An observable is only enabled when a first observer subscribes. This is a significant difference compared to promises. Due to this, processing provided to initialize a promise is always executed even if no listener is registered. This means that promises don’t wait for subscribers to be ready to receive and handle the response. When creating the promise, the initialization processing is always immediately called. Observables are lazy so we have to subscribe a callback to let them execute their initialization callback.
- Execute Several Times
Another particularity of observables is that they can trigger several times, unlike promises which can’t be used after they were resolved or rejected.
- Canceling Observables
Another characteristic of observables is that they can be canceled. For this, we can simply return a function within the initialization call of the Observable.create function. We can refactor our initial code to make it possible to cancel the timeout function.
- Error Handling
If something unexpected arises we can raise an error on the Observable stream and use the function reserved for handling errors in our subscribe routine to see what happened.
Observables vs Promises
Both Promises and Observables provide us with abstractions that help us deal with the asynchronous nature of our applications. However, there are important differences between the two,
As seen in the example above, Observables can define both the setup and teardown aspects of asynchronous behavior.
Observables are cancellable
Moreover, Observables can be retried using one of the retry operators provided by the API, such as retry and retryWhen. On the other hand, Promises require the caller to have access to the original function that returned the promise in order to have a retry capability.
Observable HTTP Events
A common operation in any web application is getting or posting data to a server. Angular applications do this with the Http library, which previously used Promises to operate in an asynchronous manner. The updated Http library now incorporates Observables for triggering events and getting new data.
Observables Array Operations
In addition to simply iterating over an asynchronous collection, we can perform other operations such as filter or map and much more as defined in the RxJS API. This is what bridges an Observable with the iterable pattern, and lets us conceptualize them as collections.
Here are two really useful array operations - map and filter. What exactly do these do?
- map will create a new array with the results of calling a provided function on every element in this array. In the below example we used it to create a new result set by iterating through each item and appending the word ‘Mr’ abbreviation in front of every employee's name.
- filter will create a new array with all elements that pass the test implemented by a provided function. Here we have used it to create a new result set by excluding any user whose salary is below 20000. Now when our subscribe callback gets invoked, the data it receives will be a list of JSON objects whose id properties are greater than or equal to 20000 salaries.
Note, the chaining function style and the optional static typing that comes with TypeScript, that we used in this example. Most important functions like filter return an Observable, as in Observables beget other Observables, similarly to promises. In order to use map and filter in a chaining sequence, we have flattened the results of our Observable using flatMap. Since filter accepts an Observable and not an array, we have to convert our array of JSON objects from data.json() to an Observablestream. This is done with flatMap.
The Angular 4 HTTP module @angular/http exposes an HTTP service that our application can use to access web services over HTTP. We’ll use this utility in our PeopleService service. We start by importing it together will all types involved in doing an HTTP request:
- import { Http, Response } from '@angular/http';
- import { Observable } from 'rxjs/Rx';
These are all types and method required to make and handle an HTTP request to a web service:
Http
The Angular 4 HTTP service that provides the API to make HTTP requests with methods corresponding to HTTP verbs like getting, post, put, etc
Response
Represents a response from an HTTP service and follows the fetch API specification
Observable is the async pattern used in Angular 4. The concept of observable comes from the observer design pattern as an object that notifies an interested party of observers when something interesting happens. In RxJs it has been generalized to manage sequences of data or events, to become composable with other observables and to provide a lot of utility functions known as operators that let you achieve amazing stuff.
Angular comes with its own HTTP library which we can use to call out to external APIs.
When we make calls to an external server, we want our user to continue to be able to interact with the page. That is, we don’t want our page to freeze until the HTTP request returns from the external server. To achieve this effect, our HTTP requests are asynchronous.
Dealing with asynchronous code is, historically, more tricky than dealing with synchronous code. In Javascript, there are generally three approaches to dealing with async code:
- Callbacks
- Promises
- Observables
Http Post
Let’s imagine we received the username and password from a form the user submitted. We would call authenticate to log in the user. Once the user is logged in we will proceed to store the token so we can include it in following requests.
http.post(URL: string, body: string, options?: RequestOptionsArgs) : Observable<Response>
The http.post signature above reads as follows. We need to provide a URL and a body, both strings and then optionally an options object. In our example, we are passing the modified headers property. http.post returns an Observable, we use a map to extract the JSON object from the response and subscribe. This will set up our stream as soon as it emits the result.
Differences between $http and angular/http
Angular 4 Http by default returns an Observable opposed to a Promise ($q module) in $http. This allows us to use more flexible and powerful RxJS operators like switchMap (flatMapLatest in version 4), retry, buffer, debounce, merge or zip. By using Observables we improve readability and maintenance of our application as they can respond gracefully to more complex scenarios involving multiple emitted values opposed to only a one-off single value.
Sample Code of app.component.employeelist.ts
Try to solve the new Formula Cube! It works exactly like a Rubik's Cube but it is only $2, from China. Learn to solve it with the tutorial on rubiksplace.com or use the solver to calculate the solution in a few steps. (Please subscribe for a membership to stop adding promotional messages to the documents)