AngularJS服务继承

AngularJS service inheritance

本文关键字:继承 服务 AngularJS      更新时间:2023-09-26

我有下一个服务:

angular.module('app').service('BaseService', function (alertService) {
   var service = {};
   service.message =  "Hello";
   service.perform = function () {
        alertService.add("success",service.message);
   };
   return service;
});

现在,我想在一些"儿童服务"中继承这项服务,并在"世界!"上重写消息。我预计调用ChildService.perform()将显示"世界!"的警报。

做这件事的正确方法是什么?

AngularJS没有提供任何机制来直接实现服务的继承,但对于您的情况,您可以使用$provide.decorator来扩展BaseService本身,也可以像使用纯JavaScript的另一个ChildService的原型一样使用它。在我的实践中,为了使服务具有可配置的状态和行为,我使用提供者。在以下所有示例中,控制台输出将为World

装饰器

如果你的模块中不需要原始的BaseService,你可以装饰它

Plunker

function AlertService() {
  this.add = function(level, message) {
    switch(level) {
      case 'success':
        console.log(message);
    }
  }
}
function BaseService(alertService) {
  this.message =  "Hello";
  this.perform = function () {
    alertService.add("success",this.message);
  };
}
angular.
  module('app',[]).
  config(['$provide', function($provide) {
    $provide.decorator('BaseService', function($delegate) {
      $delegate.message = 'World';
      return $delegate;
    });
  }]).
  service('alertService', AlertService).
  service('BaseService', ['alertService',BaseService]).
  controller('ctrl', ['BaseService', function(baseService) {
    baseService.perform();
  }]);

原型继承

Plunker

function AlertService() {
  this.add = function(level, message) {
    switch(level) {
      case 'success':
        console.log(message);
    }
  }
}
function BaseService(alertService) {
  this.message =  "Hello";
  this.perform = function () {
    alertService.add("success",this.message);
  };
}
function ChildService(BaseService) {
  angular.extend(ChildService.prototype, BaseService);
  this.message = "World";
}
angular.
  module('app',[]).
  service('alertService', AlertService).
  service('BaseService', ['alertService',BaseService]).
  service('ChildService', ['BaseService',ChildService]).
  controller('ctrl', ['ChildService', function(ChildService) {
    ChildService.perform();
  }]); 

提供商

Plunker

function AlertService() {
  this.add = function(level, message) {
    switch(level) {
      case 'success':
        console.log(message);
    }
  }
}
function BaseService() {
  var message =  "Hello";
  this.setMessage = function(msg) {
    message = msg;
  }
  function Service(alertService) {
    this.perform = function () {
      alertService.add("success", message);
    };
  }
  function Factory(alertService) {
    return new Service(alertService);
  }
  this.$get = ['AlertService', Factory];
}
angular.
  module('app',[]).
  provider('BaseService', BaseService).
  config(['BaseServiceProvider', function(baseServiceProvider) {
    baseServiceProvider.setMessage('World');
  }]).
  service('AlertService', AlertService).
  controller('ctrl', ['BaseService', function(baseService) {
    baseService.perform();
  }]);

我会稍微修改一下你的代码:

app.factory('BaseService', function () {
   //var service = {}; 
   function service(){
       this.message = "hello";
   }; 
   service.prototype.perform = function () {
        console.log('perfom', this.message);
   };
   return new service();
});

(我只是将您的alertService更改为console.log();..)

然后像这样实现继承:

app.factory('childBaseService',['BaseService', function(BaseService){
    var childBaseService = function(){
            BaseService.constructor.call(this)
            this.message = 'world!';
    };
    childBaseService.prototype = Object.create(BaseService.constructor.prototype);
    childBaseService.prototype.constructor = childBaseService;
    return new childBaseService();
}]);

你可以看到一个如何工作的例子。。最后,BaseService和childService将是BaseService构造函数(service)的实例。

console.log(BaseService instanceof BaseService.constructor); //true
console.log(childBaseService instanceof BaseService.constructor); //true

这里有一个基于Constructor/new继承的例子(我通常建议不要这样做)。

BaseService.$inject = ['alertService']
function BaseService(alertService) {
    this.message = 'hello'
    this.alertService = alertService
}
BaseService.prototype.perform = function perform() {
    this.alertService.add("success",this.message);
}

ChildService.$inject = ['alertService']
function ChildService(alertService) {
    this.message = 'hello world'
    this.alertService = alertService
}
ChildService.prototype = Object.create(BaseService.prototype)

然后你只需要将这些作为服务:

angular.module('app')
    .service('BaseService', BaseService)
    .service('ChildService', ChildService)

带有服务ASvc:的模块A

(function(angular) {
  var app = angular.module('A', []);
  app.service('ASvc', ['$http', function($http) {
     var ASvc = {
       list: function() {
         return $http({
           method: 'GET',
           url: '/A'
         });
       },
       getInstructions: function(id) {
         return $http({
           method: 'GET',
           url: '/instructions/' + id
         });
       }
     };
     return ASvc;
  }]);
})(angular);

具有服务BSvc的模块B,该服务继承自ASvc:

(function(angular) {
  var app = angular.module('B', ['A']);
  app.service('BSvc', ['$http', 'ASvc', function($http, ASvc) {
     var BSvc = {
       list: function() {
         return $http({
           method: 'GET',
           url: '/B'
         });
       }
     };
     BSvc.__proto__ = ASvc; // here you're settting the inheritance
     return BSvc;
  }]);
})(angular);

现在,当您调用BSvc.getInstructions(30775);时,您将从BSvc调用父服务(ASvcgetInstructions函数,而当您调用BSvc.list()时,您正在调用一个从BSvc中的ASvc重写的方法。遗产

顺便说一句,当我将angular作为参数传递给闭包时,我不直接从中引用全局angular变量,而是允许代码缩小器和模糊器执行以下操作:

(function(j){var c=j.module('A',[]);})(angular); // and so on

这是一件好事,我认为这是一种很好的做法;)