In this Tutorial you will learn how to communicate with the GitHub API. Although we can do this directly from the component’s controller, by doing it this way, we can couple it with the RESTful API of GitHub. In order to enforce further separation of concerns, we can extract the logic for communication with GitHub into a separate service called GitHubGateway. Open a file called github_gateway.ts and enter the following content:

<

div class=”informalexample”>

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';

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

Initially, we imported the Http class from the angular2/http module. All the HTTP-related functionality is externalized and is 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’re going to use is the one for fetching users, so we will 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’ve received in the constructor function. 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:

<

div class=”itemizedlist”>

  • request(url: string | Request, options: RequestOptionsArgs): Makes a request to the specified URL. The request can be configured using RequestOptionsArgs:
    http.request('http://example.com/', {
      method: 'get',
      search: 'foo=bar',
      headers: new Headers({
        'X-Custom-Header': 'Hello'
        })
    });
  • get(url: string, options?: RequestOptionsArgs): 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): 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): 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): 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): 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): Makes a head request to the specified URL. The request headers and other options can be configured using the second argument.
  • In next Chapter you will learn how to use Angular’s Http module to communicate with github api .

    Using Angular’s HTTP module

    Now, let’s implement the logic for importing existing users from GitHub! Open the file or create new one

    dunebook/ts/step-2/add_developer.ts and enter the following imports:

    <

    div class=”informalexample”>

    import {Response, HTTP_PROVIDERS} from 'angular2/http';
    import {GitHubGateway} from './github_gateway';

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

    <

    div class=”informalexample”>

    @Component({
      …
      providers: [GitHubGateway, FORM_PROVIDERS, HTTP_PROVIDERS]
    })
    class AddDeveloper {…}

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

    <

    div class=”informalexample”>

    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 existing developers by using the GitHubGateway instance.

    Once the user presses the Add button, we 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:

    <

    div class=”informalexample”>

    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:

    <

    div class=”informalexample”>

    this.githubAPI.getUser(model.githubHandle)

    In the getUser method, we delegate the call to the Http service’s get method, which returns an observable. In order to get the result that the observable is going to push, we need to pass a callback to its subscribe method:

    <

    div class=”informalexample”>

    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’ll get the 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 the JSON representation of their bodies. If the response fails or its body is not a valid JSON string, then we will get an error.

    <

    div class=”note”>

    <

    div class=”inner”>

    Note

    Note that in order to reduce the size of RxJS, Angular’s core team has included only its core. In order to use the methods map and catch, you need to add the following imports at add_developer.ts:

    <

    div class=”informalexample”>

    import 'rxjs/add/operator/map';
    import 'rxjs/add/operator/catch';
    

    Now let’s implement the body of the subscribe callback:

    <

    div class=”informalexample”>

    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 established the mapping between the object returned from GitHub’s API and the developer’s representation in our application. We also considered a developer as popular if she or he has above 1,000 followers.

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

    <

    div class=”note”>

    <

    div class=”inner”>

    Note

    In order to handle failed requests, we can use the catch method of the observable instances:

    <

    div class=”informalexample”>

      this.githubAPI.getUser(model.githubHandle)
      .catch((error, source, caught) => {
        console.log(error)
        return error;
      })
    
    Advertisements