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
AngularJS service inheritance
提问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 BaseService
itself or use it like a prototype of another ChildService
using 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 BaseService
in your module, you can decorate it
如果你BaseService
的模块中不需要原件,你可以装饰它
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
原型继承
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
提供者
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
) getInstructions
function from BSvc
, and when you call BSvc.list()
, you're calling a method which was overridden from ASvc
in BSvc
. Inheritance.
现在,当您调用 时BSvc.getInstructions(30775);
,您正在从 调用父级的服务 ( ASvc
)getInstructions
函数BSvc
,而当您调用 时BSvc.list()
,您正在调用从ASvc
in重写的方法BSvc
。遗产。
And BTW, when I'm passing angular
as argument to the closure, instead of referring to the global angular
variable 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 ;)
记住这是一件好事,我认为这是一种很好的做法;)