Exploring the HTTP module of Angular

Now, after we have developed both forms – for importing existing and adding new developers, it is time to implement the logic behind them in the controller of the component.

For this purpose, we will need to communicate with the GitHub API. Although we can do this directly from the component's controller, by approaching the problem this way, we would couple the component with the RESTful API of GitHub. In order to enforce better separation of concerns, we can extract the logic for communication with GitHub into a separate service called GitHubGateway. Open the file called github_gateway.ts, and enter the following content:

import {Injectable} from '@angular/core'; 
import {Http} from '@angular/http'; 
 
@Injectable() 
export class GitHubGateway { 
  constructor(private http: Http) {}
 
  getUser(username: string) { 
    return this.http 
      .get(`https://api.github.com/users/${username}`); 
  } 
} 

Initially, we import the Http class from the @angular/http module. All the HTTP-related functionalities are externalized and are outside the Angular's core. Since GitHubGateway accepts a dependency, which needs to be injected through the DI mechanism of the framework, we will decorate it with the @Injectable decorator.

The only functionality from the GitHub's API we use is the one for fetching users, so we define a single method called getUser. As an argument, it accepts the GitHub handle of the developer.

Note

Note that, if you make more than 60 requests per day to the GitHub's API, you might get the error GitHub API Rate limit exceeded. This is due to the rate limits for requests without a GitHub API token. For further information, visit https://github.com/blog/1509-personal-api-tokens .

Inside the getUser method, we use the instance of the Http service that we received in the constructor. The Http service's API stays as close to the HTML5 fetch API as possible. However, there are a couple of differences. The most significant one of them is that, at the moment of writing this content, all the methods of the Http instances return Observables instead of Promises.

The Http service instances have the following API:

  • request(url: string | Request, options: RequestOptionsArgs): This makes a request to the specified URL. The request can be configured using RequestOptionsArgs, as follows:
      http.request('http://example.com/', { 
        method: 'get', 
        search: 'foo=bar', 
        headers: new Headers({ 
          'X-Custom-Header': 'Hello'
        }) 
      }); 
  • get(url: string, options?: RequestOptionsArgs): This makes a get request to the specified URL. The request headers and other options can be configured using the second argument.
  • post(url: string, options?: RequestOptionsArgs): This makes a post request to the specified URL. The request body, headers, and other options can be configured using the second argument.
  • put(url: string, options?: RequestOptionsArgs): This makes a put request to the specified URL. The request headers and other options can be configured using the second argument.
  • patch(url: string, options?: RequestOptionsArgs): This makes a patch request to the specified URL. The request headers and other options can be configured using the second argument.
  • delete(url: string, options?: RequestOptionsArgs): This makes a delete request to the specified URL. The request headers and other options can be configured using the second argument.
  • head(url: string, options?: RequestOptionsArgs): This makes a head request to the specified URL. The request headers and other options can be configured using the second argument.

Using Angular's HTTP module

Now, let's implement the logic for importing the existing developers from GitHub. First, we will need to import the HttpModule in our AppModule:

import {HttpModule} from '@angular/http';
...

@NgModule({
  imports: [..., HttpModule],
  declarations: [...],
  providers: [...],
  bootstrap: [...]
})
class AppModule {}
...

After that, open the ch6/ts/step-2/add_developer.ts file and enter the following imports:

import {Response} from '@angular/http'; 
import {GitHubGateway} from './github_gateway'; 

Add GitHubGateway to the list of providers of the AddDeveloper component:

@Component({ 
  ... 
  providers: [GitHubGateway] 
}) 
class AddDeveloper {...} 

As the next step, we have to include the following parameters in the constructor of the class:

constructor(private githubAPI: GitHubGateway, 
  private developers: DeveloperCollection, 
  fb: FormBuilder) { 
  //... 
} 

This way, the AddDeveloper class' instances will have a private property called githubAPI.

The only thing left is to implement the addDeveloper method and allow the user to import the existing developers using the GitHubGateway instance.

Once the user presses the Add button, we will need to check whether we need to import an existing GitHub user or add a new developer. For this purpose, we can use the value of the fetchFromGitHub control:

if (this.importDevForm.controls['fetchFromGitHub'].value) { 
  // Import developer 
} else { 
  // Add new developer 
} 

If it has a truthy value, then we can invoke the getUser method of the githubAPI property and pass the value of the githubHandle control as an argument:

this.githubAPI.getUser(model.githubHandle) 

In the getUser method of the GitHubGateway instance, we delegate the call to the Http service's get method, which returns an observable. In order to get the result that the observable will push, we will need to pass a callback to its subscribe method:

this.githubAPI.getUser(model.githubHandle) 
  .map((r: Response) => r.json()) 
  .subscribe((res: any) => { 
    // "res" contains the response of the GitHub's API  
  }); 

In the preceding snippet, we first establish the HTTP get request. After this, we get the corresponding observable that, in general cases, will emit a series of values (in this case, only a single one-the response of the request) and map them to their JSON representations. If the request fails, or the response's body is not a valid JSON string, then we will get an error.

Note

Note that, in order to reduce the bundle size of Angular, the team at Google has included only the core of RxJS in the framework. In order to use the map and catch methods, you will need to add the following imports at add_developer.ts: import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch';

Now, let's implement the body of the callback we pass to subscribe:

let dev = new Developer(); 
dev.githubHandle = res.login; 
dev.email = res.email; 
dev.popular = res.followers >= 1000; 
dev.realName = res.name; 
dev.id = res.id; 
dev.avatarUrl = res.avatar_url; 
this.developers.addDeveloper(dev); 
this.successMessage = `Developer ${dev.githubHandle} successfully imported from GitHub`; 

In the preceding example, we set the properties of a new Developer instance. Here, we establish the mapping between the object returned from GitHub's API and the developer's representation in our application. We consider a developer as popular if they have more than 1,000 followers.

The entire implementation of the addDeveloper method can be found at ch7/ts/multi-page-model-driven/add_developer.ts.

Note

In order to handle failed requests, we can use the catch method of the observable instances: this.githubAPI.getUser(model.githubHandle) .catch((error, source, caught) => {    console.log(error)    return error; });

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset