在angularjs中,如何从基模块中设置一个服务,以调用使用基模块的模块中服务上的函数
How to setup a service from a base module to call a function on a service in a module that uses the base module in angularjs
我正在编写一个用于多个独立网站的服务。然而,在某些情况下,它需要触发不同的代码,这取决于它所使用的网站。我想保持每个网站的代码从基础服务分开。
下面是一些示例代码,展示了我想要的设计(尽管它不工作):
var baseModule = angular.module('baseModule', []);
baseModule.service('baseService', function() {
this.func = function() {
return ["first",
/* TODO somehow get from appropriate
service in website module */
"FIXME",
"end"];
};
});
var website1 = angular.module('website1', ['baseModule']);
website1.service('website1Service', function() {
this.someCustomValue = function() {
// Note that while this is a constant value, in
// the real app it will be more complex,
// so replacing this service with a constant provider won't work.
return "someValue";
}
});
// TODO : somehow link website1Service.someCustomValue to baseService
var website2 = angular.module('website2', ['baseModule']);
website2.service('website2Service', function() {
this.anotherValue = function() { return "anotherValue"; }
});
// TODO : somehow link website2Service.anotherValue to baseService
// Testing code:
function makeTestController(expected) {
return ['$scope', 'baseService', function($scope, baseService) {
var result = baseService.func();
if (angular.equals(result, expected)) {
$scope.outcome = "Test Passed!";
} else {
$scope.outcome = 'Test failed...'n' +
"Expected: " + angular.toJson(expected) + ''n' +
"But got : " + angular.toJson(result);
}
}];
}
website1.controller('TestController1',
makeTestController(['first', 'someValue', 'end']));
website2.controller('TestController2',
makeTestController(['first', 'anotherValue', 'end']));
// since this test uses multiple angular apps, bootstrap them manually.
angular.bootstrap(document.getElementById('website1'), ['website1']);
angular.bootstrap(document.getElementById('website2'), ['website2']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<h3>Website 1</h3>
<div id='website1'>
<div ng-controller='TestController1'>
<pre>{{outcome}}</pre>
</div>
</div>
<div id='website2'>
<h3>Website 2</h3>
<div ng-controller='TestController2'>
<pre>{{outcome}}</pre>
</div>
</div>
我已经想到了一些解决方案,但似乎没有一个是最佳的。
最明显的方法是用提供者替换baseService
服务,并允许在每个模块中配置它。这似乎是在其他模块中配置服务的标准方式。但是无法访问provider函数中的website1Service
和website2Service
,因为无法访问provider函数中的业务。这在文档中有说明:
在应用启动期间,在Angular开始创建所有服务之前,它会配置并实例化所有的提供商。我们将此称为应用程序生命周期的配置阶段。在此阶段,服务是不可访问的,因为它们还没有被创建。
解决这个问题的另一个解决方案是使用angular.injector
来找到正确的服务。然而,angular.injector
的文档暗示,您实际上只需要与第三方库进行交互。看来还有更好的办法。
最后,我可以在baseModule
中为不存在的服务(例如"baseServiceActions"
)添加依赖项,并要求在website1
和website2
中实现具有该名称的服务。当使用baseService
时,依赖注入应该将它们绑定在一起。然而,这是一个非常奇怪的工作方式,如果baseServiceActions
模块没有在使用baseModule
模块的新网站中实现,将导致糟糕的错误消息。
有更好的方法吗?如果是这样,是否有可能改变我发布的示例代码,以获得所有的测试通过?理想情况下,不应该更改任何测试代码。
我最终想出了一个相当好的解决方案。我创建了一个名为"<serviceName>Settings"
的服务,并向其添加了一个setup
函数。然后,我在我想要使用它的模块中的模块运行块中调用该设置函数。最后,我有一个在服务中调用的validate
方法,该方法使用设置来确保它已设置,如果没有设置,则抛出一个不错的错误消息。这解决了我使用其他解决方案时遇到的所有问题。
这是我的例子问题的解决方案:
var baseModule = angular.module('baseModule', []);
baseModule.service('baseService', ['baseServiceSettings', function(baseServiceSettings) {
baseServiceSettings.validate();
this.func = function() {
return ["first",
baseServiceSettings.getValue(),
"end"];
};
}]);
baseModule.service('baseServiceSettings', function() {
this.setup = function(getter) {
this.getValue = getter;
};
this.validate = function() {
if (!this.getValue) {
throw "baseServiceSettings not setup! Run baseServiceSettings.setup in a module run block to fix";
}
};
});
var website1 = angular.module('website1', ['baseModule']);
website1.run(['baseServiceSettings', 'website1Service', function(baseServiceSettings, website1Service) {
baseServiceSettings.setup(website1Service.someCustomValue);
}]);
website1.service('website1Service', function() {
this.someCustomValue = function() {
// Note that while this is a constant value, in
// the real app it will be more complex,
// so replacing this service with a constant provider won't work.
return "someValue";
}
});
var website2 = angular.module('website2', ['baseModule']);
website2.service('website2Service', function() {
this.anotherValue = function() { return "anotherValue"; }
});
website2.run(['baseServiceSettings', 'website2Service', function(baseServiceSettings, website2Service) {
baseServiceSettings.setup(website2Service.anotherValue);
}]);
// Testing code:
function makeTestController(expected) {
return ['$scope', 'baseService', function($scope, baseService) {
var result = baseService.func();
if (angular.equals(result, expected)) {
$scope.outcome = "Test Passed!";
} else {
$scope.outcome = 'Test failed...'n' +
"Expected: " + angular.toJson(expected) + ''n' +
"But got : " + angular.toJson(result);
}
}];
}
website1.controller('TestController1',
makeTestController(['first', 'someValue', 'end']));
website2.controller('TestController2',
makeTestController(['first', 'anotherValue', 'end']));
// since this test uses multiple angular apps, bootstrap them manually.
angular.bootstrap(document.getElementById('website1'), ['website1']);
angular.bootstrap(document.getElementById('website2'), ['website2']);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<h3>Website 1</h3>
<div id='website1'>
<div ng-controller='TestController1'>
<pre>{{outcome}}</pre>
</div>
</div>
<div id='website2'>
<h3>Website 2</h3>
<div ng-controller='TestController2'>
<pre>{{outcome}}</pre>
</div>
</div>
- AngularJS在不使用变量的情况下将服务注入模块中,这样就可以缩小它
- 如何在公共js模块中从web服务返回数据
- 从函数内部、类内部、模块内部访问 Angular 服务
- 角度依赖注入,使用服务在模块之间传递值
- 从 Angular 控制器访问不同模块中的角度服务
- AngularJS在自定义服务中使用角度模块
- 使用在另一个服务方法中声明为模块模式的服务方法之一
- 如何测试名为“示例”的 Angular 服务.Svc' 在我的模块中使用 mocha+chai
- ES2015 单例或服务提供商或模块,用于敲除.js组件
- 在两个不同的模块和两个不同的js文件之间共享服务
- 角度模块中的全局通信:事件总线或调解器模式/服务
- 角度依赖注入,如果将控制器、服务等分离到单独的模块中
- 替换 AngularJS 中的模块或服务
- 角度、服务和模块依赖性混淆
- 将angular服务与es6模块一起使用有意义吗
- 如何在angular js中将服务从一个模块调用到另一个模块服务
- 使用angular js中的外部模块服务解析状态
- 跨文件拆分AngularJS模块服务
- 访问模块子模块服务从主控制器
- 模块服务不可用注入服务