AngularJs in TypeScript – Services and $http

This is the 5th in a series of articles about developing for AngularJS using TypeScript. The articles in the series are:

  1. Controllers
  2. Controllers – Part 2
  3. Modules
  4. Services
  5. Services and $http (this article)
Using $http

In the previous article we added a simple MyService class which had a getPeople method that returned a static array of names. The most common type of service that I tend to write are those that use Angular’s $http service to retrieve data. When using $http I tend to make use of the get and post methods most frequently so putting together an HttpHandlerService class in TypeScript and adding methods that make it easier to use the get and post methods on the $http service would seem to be useful.

To do this we can add the following code to the KodeYak module in the service.ts file:

  export class HttpHandlerService extends Service
  {
    httpService: ng.IHttpService;
    handlerUrl: string;

    constructor( $http: ng.IHttpService )
    {
      super();
      this.httpService = $http;
    }

    useGetHandler( params: any ): ng.IPromise< any >
    {
      var result: ng.IPromise< any > = this.httpService.get( this.handlerUrl, params )
        .then( ( response: any ): ng.IPromise< any > => this.handlerResponded( response, params ) );
      return result;
    }

    usePostHandler( params: any ): ng.IPromise< any >
    {
      var result: ng.IPromise< any >  = this.httpService.post( this.handlerUrl, params )
        .then( ( response: any ): ng.IPromise< any > => this.handlerResponded( response, params ) );
      return result;
    }

    handlerResponded( response: any, params: any ): any
    {
      response.data.requestParams = params;
      return response.data;
    }

  } // HttpHandlerService class

The definition of the HttpHandlerService class has 2 properties:

  1. httpService – a pointer to the AngularJS $http service (which will be injected via dependency injection)
  2. handlerUrl – the url that will be used to get/post data

It also has 3 methods:

  1. useGetHandler – This will call the handlerUrl and use the get method on the $http service to get data
  2. usePostHandler – This will call the handlerUrl and use the post method on the $http service to post data
  3. handlerResponded – This will be called when the get/post methods of the $http service respond and it will add the request parameters to the response. The response will happen asynchronously so it can be useful to know what the request parameters were when a repsonse is received
Backend Handler

Before we create a concrete service class (based on the HttpHandlerSevice class we just created above) we need to create a backend handler that the service can call. One way to do this is to add a Generic Handler to your Visual Studio project and use that as your backend.

I added a new handler, called PeopleHandler, into a new Handlers folder of my project and updated it to look like the following:

  public class PeopleHandler : IHttpHandler
  {

    public bool IsReusable
    {
      get
      {
        return false;
      }
    }

    public void ProcessRequest( HttpContext context )
    {
      context.Response.ContentType = "text/plain";
      context.Response.Write( "Hello People" );
    }

  } // PeopleHandler class
Service Implementation

We can now add a new service class, called PeopleService, which extends HttpHandlerService and makes use of the PeopleHandler to get some data. To do this we add the following code to the MyTestApp module section of the service.ts file:

  export class PeopleService extends KodeYak.HttpHandlerService
  {
    static $inject = ['$http'];

    constructor( $http: ng.IHttpService )
    {
      this.handlerUrl = 'Handlers/PeopleHandler.ashx';
      super( $http );
    }

    getPeople(): ng.IPromise< any >
    {
      var config: any = {};
      return this.useGetHandler( config );
    }

  } // PeopleService class

The getPeopleMessage method sets up an empty object, called config, and passes this to the useGetHandler method. As we define the url for our handler in the constructor this means that calling getPeopleMessage will call out to our handler and then asynchronously receive the response.

Using the Service

We now need to update our controller (the MyController class) in the controller.ts file so that the constructor now looks like the following:

    static $inject = ['$scope', 'myService', 'peopleService'];

    constructor( $scope: IMyScope, service: MyService, peopleService: PeopleService )
    {
      super( $scope );
      $scope.message = { title: 'Hello World!!' };

      $scope.people = service.getPeople();

      peopleService.getPeopleMessage()
        .then( ( data ) => $scope.message.title = data );
    }

The last line in the constructor is of primary interest as this is the call to our new service. As you can see it calls the service methods and follows that with a call to the .then method. This is because our service is returning a promise and the .then method will only be called when the service receives the response from the handler. Once the handler returns the data it will be fed through and will feed through to the lambda expression:

  ( data ) => $scope.message.title = data

This is TypeScript notation for a lamba expresion (sometimes referred to as an arrow function) which is effectively storing the context of the method call so that when it is called (remember it’s going to be triggered asynchronously) the context is the same (we could use this within the lambda expression and it would still work).

Our lambda expression is saying that the response from calling our service method will return a single value, and we will then attach that value to the message.title property on the $scope.

In Action

What you should see if you build the project and view the page is that the Hello World message displays with the list of people’s names below it. After a short delay the Hello World message will change into a Hello People message as this is the response from the PoepleHandler.

If you refresh the page again you probably won’t even see the Hello World message as the first time it was run the PeopleHandler had to be initialised but subsequent calls go through almost instantly.

Conclusion

We now have a base class for services which use the HTTP GET and POST verbs and have added simple service that builds on that.

In the next article I will extend the handler so that it can be used to get different types of data.

4 thoughts on “AngularJs in TypeScript – Services and $http

Leave a comment