【问题标题】:How to configure dependency injection in angularjs?如何在angularjs中配置依赖注入?
【发布时间】:2013-05-19 20:34:25
【问题描述】:

我对 angularjs 应用程序的工作原理有点困惑。

首先我应该说我是一个新手 angularjs 用户,但我熟悉其他语言的其他 DI 框架(如 PHP 中的 symfony,Java 中的 spring,有点 Unity)。

这些 DI 实现中的每一个都需要类定义和 DI 配置

配置通常包括:

  • 如何应该是类注入(自动按名称或类型,或手动)
  • 如果容器应该返回一个单例实例
  • 应该使用什么工厂类来创建对象
  • serviceIds - 可以通过 serviceId 检索每个服务。这个 serviceId 表示创建实例的配置(应该注入哪些服务以及应该使用哪些参数)。

而我在 angularjs 中缺少的这个配置

有一个 dumb example 我期望这样的配置应该如何工作。我有两个服务,每个都做类似的事情,但有不同的实现

angular.module('notify', [], function($provide) {
    $provide.factory('LogNotifier', function($window) {
        return {
            messageMe: function(message) {
                $window.console.log(message);
            }
        }

    });
    $provide.factory('AlertNotifier', function($window) {
        return {
            messageMe: function(message) {
                $window.alert(message);
            }
        }
    });
});



angular.module('myModule', ['notify'], function($provide) {
  // as notifier dependency I must specify its type.
  // is there any way how I would configure after its definition
  // which notifier implementation should be used?
  $provide.factory('DataLoader', function(AlertNotifier) {
      var loader = {
          loadAllItems: function() {
              AlertNotifier.messageMe('Loading items');
              // let's asume there is ajax call and promise object return
              return [ 
                    {name: 'Item1'},
                    {name: 'Item2'}
                ];
          }
      }
      return loader;
  });
});

http://jsfiddle.net/5ZDe6/1/

我想在 LogNotifier 和 AlertNotifier 之间切换而不更改 DataLoader 服务的源代码。这可能吗?

谢谢

【问题讨论】:

    标签: javascript configuration angularjs dependency-injection


    【解决方案1】:

    在摆弄 angularjs 一周后,我意识到一件非常重要的事情。所有 angularjs 示例实际上都包含我寻找的 DI 配置。 配置本身就是一个模块定义

    我所要做的就是将模块定义与类定义分开。 这里解决了我的问题 - http://jsfiddle.net/5ZDe6/7/

    /**
    * app module configuration
    */
    angular.module('app', ['debug'], function($provide) {
        var dataLoaderFactory = function(Notifier) {
            return new my.model.DataLoader(Notifier);
        }
        // if you want to change notifier just change this injection to AlertNotifier
        dataLoaderFactory.$inject = ['LogNotifier'];  
        // Specify factory with service ID DataLoader for class my.model.DataLoader
        $provide.factory('DataLoader', dataLoaderFactory);    
    })
    .controller('AppCtrl', my.controller.ItemCtrl); // you can even specify AppCtrl implementation (e.g. CachedCtrl)
    my.controller.ItemCtrl.$inject = ['$scope','DataLoader']
    my.controller.CachedCtrl.$inject = ['$scope']
    
    /**
    * debug module configuration
    */
    angular.module('debug', [], function($provide) {
        $provide.factory('LogNotifier', function($window) {
           return new my.debug.LogNotifier($window);
        });
        $provide.factory('AlertNotifier', function($window) {
           return new my.debug.AlertNotifier($window); 
        });
    });
    

    还有与 DI 配置分开的类定义。

    /**
    * Controller class definition
    */
    my = window.my || {};
    my.controller = my.controller || {};
    my.controller.ItemCtrl = function($scope, loader) {
        $scope.items = loader.loadAllItems();
    };
    
    my.controller.CachedCtrl = function($scope) {
        $scope.items = [
            { name: 'Cached ctrl value 1'},
            { name: 'Cached ctrl value 2'}
        ]
    }
    
    /**
    * Model class definition
    */
    my.model = my.model || {};
    my.model.DataLoader = function(notifier) {
        this.notifier = notifier;
        this.loadAllItems = function() {
            this.notifier.messageMe('Loading items');
            // let's asume there is ajax call and promise object return
            return [ 
                {name: 'Item1'},
                {name: 'Item2'}
            ];
        };
    };
    
    /**
    * Some debug classes definition
    */
    my.debug = my.debug || {}
    my.debug.LogNotifier = function($window) {
        this.$window = $window;
        this.messageMe = function(message) {
            this.$window.console.log(message);
        }
    };
    my.debug.AlertNotifier = function($window) {
        this.$window = $window;
        this.messageMe = function(message) {
            this.$window.alert(message);
        }
    }
    

    我想这是实现我的要求的最简洁的方法。不幸的是,如果您真的想这样做,您必须编写更多代码

    弗兰克

    【讨论】:

    • 我想知道如何将 AngularJS 优雅的 DI 引入 PHP DI。目前 PHP DI 看起来太像服务容器了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    • 2016-03-17
    • 1970-01-01
    • 1970-01-01
    • 2018-06-08
    • 2014-07-30
    • 1970-01-01
    相关资源
    最近更新 更多