我有下一个服务:
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
调用父服务(ASvc
)getInstructions
函数,而当您调用BSvc.list()
时,您正在调用一个从BSvc
中的ASvc
重写的方法。遗产
顺便说一句,当我将angular
作为参数传递给闭包时,我不直接从中引用全局angular
变量,而是允许代码缩小器和模糊器执行以下操作:
(function(j){var c=j.module('A',[]);})(angular); // and so on
这是一件好事,我认为这是一种很好的做法;)