如何使用具有构造函数参数的TypeScript类定义AngularJS工厂

gil*_*ran 18 angularjs typescript

我想编写一个在构造函数中获取"前缀"参数的TypeScript类,该类还需要访问LogService注入.

使用纯JavaScript,您应该这样做:

angular.module('myModule', []).factory('LogWithPrefixFactory', ['LogService', function(LogService) {
    var LogWithPrefixFactory = function(prefix) {
        this.prefix = prefix;
    }

    LogWithPrefixFactory.prototype.log = function(txt) {
        // we have access to the injected LogService
        LogService.log(this.prefix, txt);
    }

    return LogWithPrefixFactory;
}]);
Run Code Online (Sandbox Code Playgroud)

因此,当您将此工厂注入控制器时,您可以像这样多次启动它(无需注入LogService):

angular.module('myModule').controller('Ctrl', function(LogWithPrefixFactory) {
    var foo = new LogWithPrefixFactory("My PREFIX");
    var foo = new LogWithPrefixFactory("My OTHER PREFIX");
}
Run Code Online (Sandbox Code Playgroud)

您如何在TypeScript类中定义此Factory?无法在函数内定义TypeScript类...此类应该可以访问LogService,但它无法在其中一个注入中获取.

bas*_*rat 20

以下是实现此目的的一种方法:

class LogWithPrefixFactory {
    static LogService;
    constructor(prefix) {
        this.prefix = prefix;
    }

    log = function(txt) {
        // we have access to the injected LogService
        LogService.log(this.prefix, txt);
    }
}

angular.module('myModule', []).factory('LogWithPrefixFactory', ['LogService', function(LogService) {
    LogWithPrefixFactory.LogService = LogService;
    return LogWithPrefixFactory;
}]);


angular.module('myModule').controller('Ctrl', function(LogWithPrefixFactory) {
    var foo = new LogWithPrefixFactory("My PREFIX");
    var foo = new LogWithPrefixFactory("My OTHER PREFIX");
});
Run Code Online (Sandbox Code Playgroud)

理性:你实际上想要一个LogWithPrefixFactory中的静态属性(使用JS中的闭包),并且你希望它来自Angular.

  • 这里没有常数.只有静态.静态只意味着类的所有实例共享相同的非实例引用(实际上与服务的工作方式相同).这里唯一的区别是,不是静态注入器返回所有实例共享的静态服务,而是具有没有注入器的静态服务. (2认同)

Kos*_*rov 13

至少有2个选项.

第一个选项,LogWithPrefixFactory提供一个getInstance返回前缀记录器的方法.

module services {
  class LogService {
    $window: any;

    constructor($window: any) {
      this.$window = $window;
    }

    log(prefix: string, txt: string) {
      this.$window.alert(prefix + ' :: ' + txt);
    }
  }
  angular.module('services').service('LogService', ['$window', LogService]);


  export interface ILog {
    log: (txt) => void;
  }

  export class LogWithPrefixFactory {
    logService: LogService;

    constructor(logService: LogService) {
      this.logService = logService;
    }

    getInstance(prefix: string): ILog {
      return {
        log: (txt: string) => this.logService.log(prefix, txt);
      }
    }
  }

  angular.module('services').service('LogWithPrefixFactory', ['LogService', services.LogWithPrefixFactory]);
}
Run Code Online (Sandbox Code Playgroud)

哪个可以在控制器中使用,如:

this.log1 = logWithPrefixFactory.getInstance("prefix1");
this.log2 = logWithPrefixFactory.getInstance("prefix2");
Run Code Online (Sandbox Code Playgroud)

在这里完成plunker .

第二个选项(类似于另一个答案),给Angular另一个函数用作构造函数,它手动处理LogService构造函数注入(个人而言,我不喜欢static).

angular.module('services').service('LogWithPrefixFactory', ['LogService', function(logService) {
    return function LogWithPrefixFactory(prefix) {
      return new LogWithPrefix(prefix, logService);
    };
}]);
Run Code Online (Sandbox Code Playgroud)

哪个可以在控制器中使用,如:

this.log1 = new LogWithPrefixFactory("prefix1");
this.log2 = new LogWithPrefixFactory("prefix2");
Run Code Online (Sandbox Code Playgroud)

甚至:

this.log1 = LogWithPrefixFactory("prefix1");
this.log2 = LogWithPrefixFactory("prefix2");
Run Code Online (Sandbox Code Playgroud)

LogWithPrefixFactory在控制器中注入但它不是TypeScript类构造函数,它是中间函数,它在"手动"注入之后返回类的实际实例LogService.

在这里完成plunker .

注意:这些掠夺者在浏览器上同步编译typescript.我只在Chrome上测试过它.不保证他们会工作.最后,我手动添加了angular.d.ts的一小部分.完整文件非常大,我的代理不允许大的POST.


Cod*_*-EZ 8

我已经实现了如下

module Dashboard {
    export class LayoutServiceFactory {
        static $inject = ["$q", "$http"];
        private q: ng.IQService;
        private http: ng.IHttpService;

        constructor(private $q: ng.IQService, private $http: ng.IHttpService) {
            this.q = $q;
            this.http = $http;
        }

        getDataFromServer(serviceUrl) {
            var deferred = this.q.defer();
            this.http.get(serviceUrl, null)
                .then(response => {

                    deferred.resolve((response) as any);

                });
            return deferred.promise;
        }

        static factory() {
            var instance = ($q: ng.IQService, $http: ng.IHttpService) =>
                new LayoutServiceFactory($q, $http);
            return instance;
        }
    }

    appModule.factory("LayoutService", LayoutServiceFactory.factory());
}
Run Code Online (Sandbox Code Playgroud)