AngularJS中的可选依赖关系 [英] Optional dependencies in AngularJS

查看:123
本文介绍了AngularJS中的可选依赖关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在AngularJS中实现一个跨多个页面使用的控制器。它利用一些服务。其中有些是加载在所有页面上,有些不是。我的意思是它是在不同的文件中定义的,这些文件是独立加载的。但是如果我不在所有页面上加载这些服务,我会收到错误:

 错误:未知提供者:firstOtionalServiceProvider<  -  firstOtionalService 

所以,我需要在所有页面上加载脚本。我可以在Angular中声明依赖关系吗?例如:

  myApp.controller('MyController',['$ scope','firstRequiredService','secondRequiredService' :firstOptionalService','optional:secondOptionalService',function($ scope,firstRequiredService,secondRequiredService,firstOptionalService,secondOptionalSerivce){

//不需要检查,因为firstRequiredService不能为空
firstRequiredService .alwaysDefined();

//如果依赖关系未解决,我希望Angular将null设置为参数,并检查
if(firstOptionalService){
firstOptionalService.mayBeUndefinedSoCheckNull();
}

}]);


解决方案

不,Angular还不支持可选依赖关系盒子。你最好将所有的依赖项放在一个模块中,并将其作为一个Javascript文件加载。如果您需要另一组依赖关系 - 请考虑在另一个JS中创建另一个模块,并将所有常见的依赖关系放置到常见的JS中。



但是,您所描述的行为可以通过 $ inject 服务。您只需将 $ inject 而不是所有的依赖项注入到控制器中,并手动从其中提取依赖关系,检查它们是否存在。就是这样:



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','$ inject',function($ scope,$ injector){
var common;
var first;
var second;

try {
common = $ inject.get('commonService');
console.log('Injector has common service!');
} catch(e){
console.log('注射器没有通用服务!');
}
try {
first = $ injector.get ('firstService');
console.log('Injector has first service!');
} catch(e){
console.log('注射器没有第一个服务! );
}
try {
second = $ injector.get('secondService');
console.log('Injector has second service!');
} catch(e){
console.log('注入器没有第二个服务!');
}

if(common){
common.action ();
}
if(first){
first.action( );
}
if(second){
second.action();
}
}]);

1.js:

  myApp.service('firstService',function(){
this.action = function(){
console.log加载');
}
});

2.js:

  myApp.service('secondService',function(){
this.action = function(){
console.log加载');
}
});

现在见这个plunk !尝试玩< script> 标签,并观看控制台输出。



而且,如@Problematic所说,您可以使用 $ injector.has(),从AngularJS 1.1.5开始。


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

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

}]);

解决方案

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.

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');
    }
});

See it live in this plunk! Try to play with <script> tags and watch for console output.

P.S. And, as @Problematic said, you can use $injector.has(), starting from AngularJS 1.1.5.

这篇关于AngularJS中的可选依赖关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆