ialexander
ialexander

Reputation: 910

Migrating Angular based logger service to real Typescript (not just module wrapped Angular)

I'm having my first go at translating Angular to Typescript. In theory, I really like TS and what it has to offer - but I'm having a miserable time mixing TS and Angular. The code:

module logger { 

 exceptionHandlerProvider.$inject = ["$injector"]

  function exceptionHandlerProvider($injector, exception:any, cause:any) { 
  return function(exception: any, cause: any) {
      var $http = $injector.get('$http');
      var alertService = $injector.get('alertService');

      $http({
          url: '/api/log/',
          method: 'POST',
          data: $.param({
              exception: exception,
              cause: cause,
              apiRequest: true
          }),
          headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
      }).error(function(data) {
          alertService.addAlert({ msg: exception, type: 'error' });
          console.log(exception);
      });
  };


}

  angular.module('logger').factory('$exceptionHandler', exceptionHandlerProvider);

}

This doesn't feel much like I'm taking advantage of Typescript - but it works. My problems with the following code are, one, it just feels like I'm wrapping my Angular code in a module. And two, the code doesn't work. Basically, no matter what I try, I can't figure out how to translate the function notation of Angular to the Class notation of Typescript. I know once I get the hang of it, it will be worth it, but I've tried so many different ways to get this working. I usually get errors where I have a circular dependency, or that the class is not returning the correct type, or injector errors.

So I try:

module logger { 

export class $exceptionHandlerProvider {

    http: ng.IHttpService;
    alertService: services.AlertService;

    constructor(Http: ng.IHttpService, AlertService: services.AlertService, exception: any, cause: any){
        this.http = Http;
        this.alertService = AlertService;
        return this.$exceptionHandler(exception, cause);
    }

     public $exceptionHandler (exception:any, cause:any) { 
      return function(exception: any, cause: any) {
          this.http({
              url: '/api/log/',
              method: 'POST',
              data: $.param({
                  exception: exception,
                  cause: cause,
                  apiRequest: true
              }),
              headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
          }).error(data => {
              this.alertService.addAlert({ msg: exception, type: 'error' });
              console.log(exception);
          });
      };
    }
   } 
 } 

If anyone could recommend a good resource for working with Angular in Typescript, but also for translating this snippet to Typescript it would be appreciated.

Upvotes: 0

Views: 407

Answers (1)

Artem
Artem

Reputation: 1870

You actually have circular dependency: $http -> $exceptionHandler -> $http. Also $exceptionHandler is not usual object service, it is a function, so if you want to declare a class you should make some trick:

module logger {
    class ExceptionHandler {

        static $inject = ['$injector'];

        constructor(injector: ng.auto.IInjectorService) {
            ExceptionHandler.injector = injector;
            return <any>ExceptionHandler.handle.bind(ExceptionHandler);
        }

        private static injector: ng.auto.IInjectorService;

        private static handle(exception: any, cause: any) {
            var http = this.injector.get<ng.IHttpService>('$http');
            var alertService = this.injector.get<services.AlertService>('alertService');

            http(...);
        }
    }

    angular.module('logger', []).factory('$exceptionHandler', ExceptionHandler);
}

But I recommend you to just add types to your first approach and don't use this twisted one. TypeScript is not ClassScript.

Middle way:

module logger {
    class ExceptionHandler {
        constructor(private injector: ng.auto.IInjectorService) {
            this.handle = this.handle.bind(this);
        }

        handle(exception: any, cause: any) {
            var http = this.injector.get<ng.IHttpService>('$http');
            var alertService = this.injector.get<services.AlertService>('alertService');

            http(...);
        }
    }

    angular.module('logger', []).factory('$exceptionHandler',
        ['$injector', injector => new ExceptionHandler(injector).handle])
}

Upvotes: 1

Related Questions