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 usingRequestOptionsArgs
: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
andGitHubGateway
to the list of providers of theAddDeveloper
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 calledgithubAPI
.The only thing left is to implement the
addDeveloper
method and allow the user to import existing developers by using theGitHubGateway
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 thegithubAPI
property and pass the value of thegithubHandle
control as an argument:<
div class=”informalexample”>
this.githubAPI.getUser(model.githubHandle)
In the
getUser
method, we delegate the call to theHttp
service’sget
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 itssubscribe
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
andcatch
, you need to add the following imports atadd_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 atch7/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; })