AngularJS 中的可选依赖项 [英] Optional dependencies in AngularJS
问题描述
我正在尝试在 AngularJS 中实现一个跨多个页面使用的控制器.它利用了一些服务.其中一些已加载到所有页面上,有些则没有.我的意思是它定义在不同的文件中,并且这些文件是独立加载的.但是如果我没有在所有页面上加载这些服务,我就会出错:
I'm trying to implement a controller in AngularJS which is used across multiple pages. It makes use of some services. Some of them are loaded on all pages, some - not. I mean it is defined in different files, and these files are loaded independently. But if I do not load these services on all pages I got error:
Error: Unknown provider: firstOtionalServiceProvider <- firstOtionalService
所以,我需要在所有页面上加载脚本.我可以在 Angular 中将依赖声明为可选吗?例如:
So, I need to load scripts on all pages. Can I declare dependency as optional in Angular? E.g:
myApp.controller('MyController', ['$scope', 'firstRequiredService', 'secondRequiredService', 'optional:firstOptionalService', 'optional:secondOptionalService', function($scope, firstRequiredService, secondRequiredService, firstOptionalService, secondOptionalSerivce){
// No need to check, as firstRequiredService must not be null
firstRequiredService.alwaysDefined();
// If the dependency is not resolved i want Angular to set null as argument and check
if (firstOptionalService) {
firstOptionalService.mayBeUndefinedSoCheckNull();
}
}]);
推荐答案
不,Angular 尚不支持开箱即用的可选依赖项.您最好将所有依赖项放入一个模块中,并将其作为一个 Javascript 文件加载.如果您需要另一组依赖项 - 考虑在另一个 JS 中创建另一个模块,并将所有公共依赖项放到公共 JS 中.
No, Angular does not yet support optional dependencies out of the box. You'd better put all your dependencies into a module and load it as one Javascript file. If you need another set of dependencies - consider creating another module in another JS and putting all common dependencies to common JS.
但是,您描述的行为可以通过 $injector
服务.您只需将 $injector
而不是所有依赖项注入控制器,然后手动从中提取依赖项,检查它们是否存在.就是这样:
However, behavior you've described can be achieved with $injector
service. You simply inject $injector
instead of all your dependencies to a controller and pull dependencies from it manually, checking if they exist. That's it:
index.html:
<!DOCTYPE html>
<html data-ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js"></script>
<script src="app.js"></script>
<script src="1.js"></script>
<script src="2.js"></script>
<title>1</title>
</head>
<body data-ng-controller="DemoController">
</body>
</html>
app.js:
var myApp = angular.module('myApp', []);
myApp.service('commonService', function(){
this.action = function(){
console.log('Common service is loaded');
}
});
myApp.controller('DemoController', ['$scope', '$injector', function($scope, $injector){
var common;
var first;
var second;
try{
common = $injector.get('commonService');
console.log('Injector has common service!');
}catch(e){
console.log('Injector does not have common service!');
}
try{
first = $injector.get('firstService');
console.log('Injector has first service!');
}catch(e){
console.log('Injector does not have first service!');
}
try{
second = $injector.get('secondService');
console.log('Injector has second service!');
}catch(e){
console.log('Injector does not have second service!');
}
if(common){
common.action();
}
if(first){
first.action();
}
if(second){
second.action();
}
}]);
1.js:
myApp.service('firstService', function(){
this.action = function(){
console.log('First service is loaded');
}
});
2.js:
myApp.service('secondService', function(){
this.action = function(){
console.log('Second service is loaded');
}
});
在 这个 plunk 中现场观看!尝试使用 标签并观察控制台输出.
See it live in this plunk! Try to play with <script>
tags and watch for console output.
附言而且,正如@Problematic 所说,您可以使用 $injector.has()
,从 AngularJS 1.1.5 开始.
P.S. And, as @Problematic said, you can use $injector.has()
, starting from AngularJS 1.1.5.
这篇关于AngularJS 中的可选依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!