【问题标题】:AngularJS dependency injection swap implementationAngularJS 依赖注入交换实现
【发布时间】:2014-01-08 04:18:35
【问题描述】:

我仍在学习 AngularJS,并且对它们的依赖注入风格有疑问。例如,假设我有一个DataProcessor 服务,它有一个processData 方法,该方法接受uri 参数,它需要读取该数据(可能是xml、json 等)然后执行一些操作在上面。 DataProcessor 构造函数接受DataReader 接口的实现,该接口知道如何读取特定文件类型。以下是我所说的一些示例服务:

// implementations of the DataReader interface
myApp.service('XmlDataReader', function() {
    this.readData = function(uri) {
        // read xml data from uri
    }
}]);

myApp.service('JsonDataReader', function() {
    this.readData = function(uri) {
        // read json data from uri
    }
}]);

// data processing service that takes in an implementation of a DataReader
myApp.service('DataProcessor', ['DataReader', function(DataReader) {

    this.processData = function(uri) {
        var readData = DataReader.readData(uri);

        // process data and return it
    }
}]);

从典型的依赖注入角度来看,DataReader 的特定类型可以传递到 DataProcessor 并像这样使用:

var dataProcessor = new DataProcessor(new JsonDataReader());
var processedData = dataProcessor.processData('dataz.json');

AngularJS 的做法是什么?

【问题讨论】:

    标签: angularjs angularjs-injector


    【解决方案1】:

    由于 DI 的工作方式,您永远不必创建服务实例。你所做的就是将你需要的服务注入到你的控制器中,它应该可以正常工作。在上述情况下,您的控制器可能被定义为:

    var app = angular.module('App', ['DataProcessor']);
    
    function MyController($scope, DataProcessor) {
        var uri = '';
        DataProcessor.processData(uri);
    }
    

    您需要做的唯一另一件事是确保“App”是您在“ng-app”指令中指定的名称,并确保您的页面包含带有“DataProcessor”的JS文件 你包含了 Angular 应用程序模块(从技术上讲,这些模块甚至可以在同一个文件中定义)。希望这会有所帮助!

    编辑

    顺便说一句,如果您需要缩小 - 以下是您将如何定义控制器:

    var app = angular.module('App', ['DataProcessor']);
    
    // if you need to minify:
    var MyController = ['$scope', 'DataProcessor',
        function($scope, DataProcessor) {
            var uri = '';
            DataProcessor.processData(uri);
        }
    ];
    

    其他建议

    我目前对服务的理解是用于在控制器之间共享数据或代码。如果此数据处理特定于该控制器,您可能会考虑将“ProcessData”实现直接移动到您的控制器中。有时,这样的更改可能比处理服务中的数据更简单。如果您确实在服务中处理数据,您可能仍希望将该数据写回范围。在这种情况下,您可以将 $scope 作为参数传递到服务例程中。由于我对您的用例了解不多,因此请对这些建议持保留态度。祝你好运!

    【讨论】:

    • 但是如果 DataProcessor 需要 DataReader 的特定实现(例如 JsonDataReader),你怎么做呢?依赖注入的一个主要好处是能够交换实现。我在 AngularJS 中找到的所有示例都注入了它们的“依赖项”,但它们始终只是指向某个单一的、特定的具体实现。
    • 我同意你所说的。我可以想到交换实现的一种方法是让两个 JS 文件定义相同的服务并使用包含(即脚本包含)来决定控制器将使用哪个。总的来说,我认为 JavaScript 不支持经典继承,这使得一些 DI 概念变得更加困难。
    【解决方案2】:

    做这样的事情:

    myApp.service('DataProcessor', ['$injector', 'valueRecipeOfTheServicename', function($injector, valueRecipeOfTheServicename) {
    
        this.processData = function(uri) {
            var service = $injector.get(valueRecipeOfTheServicename);
    
            // process data and return it
        }
    }]);
    

    $injetcor.get() 检索服务

    【讨论】:

      【解决方案3】:

      基于 Noypi Gilas answer,我使用服务名称初始化控制器并通过 $injetcor.get() 检索它:

      myApp.service('DataProcessor', ['$injector', function($injector) {
          var service;
      
          $scope.init = function (serviceName) {
              service = $injector.get(serviceName);
          }
      
          this.processData = function(uri) {
              // use the service ...
          }
      }]);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-04
        • 2016-03-17
        • 2011-01-03
        • 2014-07-30
        相关资源
        最近更新 更多