javascript AngularJS 服务继承

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26642174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 06:15:35  来源:igfitidea点击:

AngularJS service inheritance

javascriptangularjs

提问by Alexey

I have next service:

我有下一个服务:

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

Now I want to inherit this service in some 'ChildService' with overriding message on "World!". I expect that calling ChildService.perform() will show alert with "World!".

现在我想在一些“ChildService”中继承这个服务,并在“World!”上覆盖消息。我希望调用 ChildService.perform() 会显示带有“World!”的警报。

What is proper way to do this?

这样做的正确方法是什么?

回答by Vadim

AngularJS does not provide any mechanism to implement inheritance of services directly, however for your case you can use $provide.decoratorto extend BaseServiceitself or use it like a prototype of another ChildServiceusing plain JavaScript. In my practice, in order to have service with configurable state and behaviour I use providers. In all of the following examples the console output will be World.

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

Decorator

装饰器

If you don't need the original BaseServicein your module, you can decorate it

如果你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();
  }]);

Prototypical Inheritance

原型继承

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();
  }]); 

Provider

提供者

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();
  }]);

回答by rahpuser

I would modify a little bit your code:

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

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

(I just change your alertService for an console.log();.. )

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

then implement inheritance like this:

然后像这样实现继承:

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();

}]);

You could see a exampleof how this works.. at the end, BaseService and childService would be instances of BaseService constructor ( service ).

您可以看到它是如何工作的示例。最后, BaseService 和 childService 将是 BaseService 构造函数 ( service ) 的实例。

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

回答by Sacho

Here is an example, based on Constructor/new inheritance(which I would generally recommend against).

这是一个基于构造函数/新继承的示例(我通常不建议这样做)。

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)

And then you would just include these as services:

然后你只需将这些作为服务包括在内:

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

回答by Bruno Finger

Module A with service ASvc:

带有服务 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);

Module B with service BSvc which inherits from ASvc:

带有从 ASvc 继承的服务 BSvc 的模块 B:

(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);

Now, when you call BSvc.getInstructions(30775);, you're calling the parent's service (ASvc) getInstructionsfunction from BSvc, and when you call BSvc.list(), you're calling a method which was overridden from ASvcin BSvc. Inheritance.

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

And BTW, when I'm passing angularas argument to the closure, instead of referring to the global angularvariable directly from within it, I'm allowing code minifiers and obfuscators to do things like this:

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

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

It's a good thing to have in mind and I consider it being a good practice ;)

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