Книга: Angular 2 Cookbook
Назад: 5. ReactiveX Observables
Дальше: Implementing a Publish-Subscribe model using Subjects

Basic utilization of Observables with HTTP

In Angular 2, the Http module now by default utilizes the Observable pattern to wrap XMLHttpRequest. For developers that are familiar with the pattern, it readily translates to the asynchronous nature of requests to remote resources. For developers that are newer to the pattern, learning the ins and outs of Http Observables is a good way to wrap your head around this new paradigm.

Note

The code, links, and a live example related to this are available at .

Getting ready

For the purpose of this example, you'll just serve a static JSON file to the application. However note that this would be no different if you were sending requests to a dynamic API endpoint.

Begin by creating a skeleton component, including all the necessary modules for making HTTP requests:

[app/article.component.ts]      import {Component} from '@angular/core';   import {Http} from '@angular/http';              @Component({     selector: 'article',     template: `                          <h1>{{title}}</h1>       <p>{{author}}</p>     `   })   export class ArticleComponent {     title:string;     body:string;     constructor (private http: Http) {     }   }   

For this example, assume there is a JSON file inside the static directory named article.json:

[article.json]      {     "title": "Orthopedic Doctors Ask City for More Sidewalk Cracks",     "author": "Jake Hsu"   }   

How to do it...

Since you have already injected the Http service, you can begin by defining the get request:

[app/article.component.ts]      import {Component} from '@angular/core';   import {Http} from '@angular/http';              @Component({     selector: 'article',     template: `                          <h1>{{title}}</h1>       <p>{{author}}</p>     `   })   export class ArticleComponent {     title:string;     body:string;     constructor (private http_: Http) {       http_.get('static/article.json');     }   }   

This creates an Observable instance, but you still need to add instructions on how to handle the raw string of the response.

Note

At this point, you will notice that this does not actually fire a browser GET request. This is covered in this recipe's There's more section.

Since you know the request will return JSON, you can utilize the json() method that a Response would expose. This can be done inside the map() method. However, the Observable does not expose the map() method by default, so you must import it from the rxjs module:

[app/article.component.ts]      import {Component} from '@angular/core';   import {Http} from '@angular/http';   import 'rxjs/add/operator/map';      @Component({     selector: 'article',     template: `                          <h1>{{title}}</h1>       <p>{{author}}</p>     `   })   export class ArticleComponent {     title:string;     author:string;     constructor (private http_: Http) {       http_.get('static/article.json') .map(response => response.json());     }   }   

So far so good, but you're still not done. The preceding code will create the Observable instance, but you still have to subscribe to it in order to handle any data it would emit. This can be accomplished with the subscribe() method, which allows you to attach the callback and error handling methods of observer:

[app/article.component.ts]      import {Component} from '@angular/core';   import {Http} from '@angular/http';   import 'rxjs/add/operator/map';      @Component({     selector: 'article',     template: `                          <h1>{{title}}</h1>       <p>{{author}}</p>     `   })   export class ArticleComponent {     title:string;     author:string;     constructor (private http_: Http) {       http_.get('static/article.json')         .map(response => response.json())         .subscribe(           article => {             this.title = article.title;             this.author = article.author;           },           error => console.error(error));     }   }   

With all of this, the GET request will return the JSON file, and the response data will be parsed and its data interpolated into the DOM by the component.

How it works...

The previous section gave a good high-level overview of what was happening, but it is useful to break things down more carefully to understand what each individual step accomplishes.

Observable<Response>

The Http service class exposes the methods get(), post(), put(), and so on—all the HTTP verbs that you would expect. Each of these will return Observable<Response>, which will emit a Response instance when the request is returned:

console.log(http_.get('static/article.json'));   // Observable { ... }   

Note

It sounds obvious, but Observables are observed by an observer. The observer will wait for Observable to emit objects, which in this example takes the form of Response.

The RxJS map() operator

The Response instance exposes a json() method, which converts the returned serialized payload string into its corresponding in-memory object representation. You would like to be able to pass a regular object to the observer handler, so the ideal tool here is a wedge method that still gives you an Observable in the end:

console.log(http_.get('static/article.json')     .map(response => response.json()));   // Observable {source: Observable, operator: MapOperator, ...}   

Recall that the canonical form of Observables is a stream of events. In this case, we know there will only ever be one event, which is the HTTP response. Nonetheless, all the normal operators that would be used on a stream of events can just as easily be used on this single-event Observable.

In the same way that Array.map() can be used to transform each instance in the array, Observable.map() allows you to transform each event emitted from Observable. More specifically, it creates another Observable that emits the modified event passed from the initial observable.

Subscribe

Observable instances expose a subscribe() method that accepts an onNext handler, an onError handler, and an onCompleted handler as arguments. These handlers correspond to the events in the life cycle of the Observable when it emits Response instances. The parameter for the onNext method is whatever is emitted from the Observable. In this case, the emitted data is the returned value from map(), so it will be the parsed object that has returned after invoking json() on the Response instance.

All these methods are optional, but in this example, the onNext and onError methods are useful.

Note

Together, these methods when provided to subscribe() constitute what is identified as the observer.

http_.get('static/article.json')     .map(respose => respose.json())     .subscribe(       article => {         this.title = article.title;         this.body = article.body;       },       error => console.error(error));   

With all of this together, the browser will fetch the JSON and parse it, and the subscriber will pass its data to the respective component members.

There's more...

When constructing this recipe piece by piece, if you are watching your browser's network requests as you assemble it, you will notice that the actual GET request is not fired until the subscribe() method is invoked. This is because the type Observable you are using is "cold".

Hot and cold Observables

The "cold" designation means that the Observable does not begin to emit until an observer begins to subscribe to it. This is different from a "hot" Observable, which will emit items even if there are no observers subscribed to it. Since this means that events that occur before an observer is attached are lost, HTTP Observables demand a cold designation.

The onNext method is termed "emission" since there is associated data that is being emitted. The onCompleted and onError methods are termed "notifications," as they represent something of significance, but they do not have an associated event that would be considered part of the stream.

See also

  • Implementing a Publish-Subscribe model using Subjects shows you how to configure input and output for RxJS Observables
  • Building a fully featured AutoComplete with Observables gives you a broad tour of some of the utilities offered to you as part of the RxJS library
Назад: 5. ReactiveX Observables
Дальше: Implementing a Publish-Subscribe model using Subjects

thank you
Flame
cant read the code since it is all on a single line. Also this comments section is russian
Rakuneque
DATA COLLECTION AND ANALYSIS Two reviewers extracted data and assessed methodological quality independently lasix torsemide conversion Many others were in that space already