AngularJS中的可选依赖项

mol*_*cha 51 javascript dependency-injection optional-parameters angularjs

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

Error: Unknown provider: firstOtionalServiceProvider <- firstOtionalService
Run Code Online (Sandbox Code Playgroud)

所以,我需要在所有页面上加载脚本.我可以在Angular中将依赖声明为可选的吗?例如:

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

}]);
Run Code Online (Sandbox Code Playgroud)

Pro*_*tic 59

显然不使用自动注射.但是,您可以注入进样器并检查服务:

myApp.controller('MyController', [
    '$scope', '$injector', 'firstRequiredService', 'secondRequiredService', 
    function ($scope, $injector, firstRequiredService, secondRequiredService) {
        if ($injector.has('firstOptionalService')) {
            var firstOptionalService = $injector.get('firstOptionalService');
        }
    }
]);
Run Code Online (Sandbox Code Playgroud)

  • 太好了!从我的观点来看,这是正确的答案 (3认同)
  • 我喜欢@ madhead的答案,因为它使用`$ injector.has`而不是`try` /`catch` (2认同)

mad*_*ead 54

不,Angular尚未支持开箱即用的可选依赖项.您最好将所有依赖项放入模块并将其作为一个Javascript文件加载.如果您需要另一组依赖项 - 考虑在另一个JS中创建另一个模块并将所有常见依赖项放到常见的JS中.

但是,您所描述的行为可以通过$injector服务来实现.您只需将$injector所有依赖项注入控制器并手动从中拉出依赖项,检查它们是否存在.而已:

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>
Run Code Online (Sandbox Code Playgroud)

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();
    }
}]);
Run Code Online (Sandbox Code Playgroud)

1.js:

myApp.service('firstService', function(){
    this.action = function(){
        console.log('First service is loaded');
    }
});
Run Code Online (Sandbox Code Playgroud)

2.js:

myApp.service('secondService', function(){
    this.action = function(){
        console.log('Second service is loaded');
    }
});
Run Code Online (Sandbox Code Playgroud)

这个插件中看到它!尝试使用<script>标签并观察控制台输出.

PS并且,正如@Problematic所说,你可以使用$injector.has(),从AngularJS 1.1.5开始.


Buu*_*yen 13

我可能会选择@ Proplematic建议使用$ injector.但是,我可以想到另一个解决方案:null在引导程序文件中注册所有服务及其默认值(例如).加载其他文件后,后面的定义将覆盖默认定义,稍微创建您想要的效果.

var app = angular.module('plunker', []);

app.value("service1", null)
   .value("service2", null)
   .factory("service1", function() { return "hello"; });

app.controller('MainCtrl', function($scope, service1, service2) {
  console.log(service1); // hello
  console.log(service2); // null
});
Run Code Online (Sandbox Code Playgroud)

演示链接


Ken*_*nne 9

这就是我解决它的方式:

var deps = [];

try {
    //Check if optionalModule is available
    angular.module('app').requires.push('optionalModule');
    deps.push('optionalModule');
} catch(e){
    console.log("Warn: module optionalModule not found. Maybe it's normal");
}

angular.module('app', deps).factory('stuff', function($injector) {
    var optionalService;

    if($injector.has('optionalService')) {
        optionalService = $injector.get('optionalService');
    } else {
        console.log('No waffles for you, dear sir');
    }
});
Run Code Online (Sandbox Code Playgroud)


小智 5

试试这种方式..

try {
    angular.module('YourModule').requires.push('Optional dependency module');
} catch(e) {
    console.log(e)
}
Run Code Online (Sandbox Code Playgroud)

'requires'是一个依赖模块数组.