导入多个AngularJS模块的工厂

And*_*loi 6 javascript angularjs

我想知道是否有办法将我在AngularJS模块中定义的所有工厂导入控制器而无需全部列出.假设我有一个名为contains的文件foo.js:

angular.module("Foo", [])
.factory("Bar1", function() {...})
.factory("Bar2", function() {...})
.factory("Bar3", function() {...})
.factory("Bar4", function() {...});
Run Code Online (Sandbox Code Playgroud)

现在,在我的controller.js档案中,我有:

angular.module("myApp.controllers", ["Foo"]).
controller("MainCtrl", ["Bar1", "Bar2", "Bar3", "Bar4", function(bar1, bar2, bar3, bar4) {
    //do stuff with the various bars
}]);
Run Code Online (Sandbox Code Playgroud)

我只是想知道控制器是否有任何优雅的方式,因为它已经导入模块Foo,看到它的所有工厂(或提供者,或服务,或指令).

Mic*_*x2a 5

对的,这是可能的.

您可以动态加载模块以检查其_invokeQueue字段(请参阅/sf/answers/1358852351/),以便检索模块中定义的所有工厂/控制器/等的名称.

然后,您可以使用该$injector服务实际检索工厂.

为了演示,我已经创建了一个快速的演示证明.您应该能够直接将IntrospectModule工厂复制并粘贴到您的应用中以获得此功能.

// Creating some test services
angular.module('test-services', [])
    .factory('Bar1', function() {
        return { 'stuff': function() { return 'calling bar1' } };
    })
    .factory('Bar2', function() {
        return { 'stuff': function() { return 'calling bar2' } };
    });

angular.module('myapp', ['test-services'])
    .factory('IntrospectModule', function($injector) {
        // This factory will dynamically return all services/controllers/directives/etc
        // given the module name.

        return function (moduleName) {
            var out = {};
            angular.module(moduleName)._invokeQueue.forEach(function(item) {
                var name = item[2][0];
                out[name] = $injector.get(name);
            });
            return out;
        };
    })
    .controller('MainCtrl', function($scope, IntrospectModule) {
        // And now I'm using it
        var testServices = IntrospectModule('test-services');
        $scope.test = testServices.Bar1.stuff();
    });
Run Code Online (Sandbox Code Playgroud)

这是上面的一个工作的plnkr.


或者,如果感觉过于苛刻,您可以尝试创建一个"复合"工厂:

angular.module("test-services", [])
    .factory("Bar1", function() {...})
    .factory("Bar2", function() {...})
    .factory("Bar3", function() {...})
    .factory("Bar4", function() {...})
    .factory("EveryBar", ["Bar1", "Bar2", "Bar3", "Bar4", 
        function(bar1, bar2, bar3, bar4) {
            return {
                'bar1': bar1, 
                'bar2': bar2,
                'bar3': bar3,
                'bar4': bar4
            };
        }]);
Run Code Online (Sandbox Code Playgroud)

然后,在您的控制器内,执行:

angular.module("myApp.controllers", ["test-services"]).
controller("MainCtrl", ["EveryBar", function(everyBar) {
    everyBar.bar1.stuff();
}]);
Run Code Online (Sandbox Code Playgroud)

显然,这种方法的缺点是它在设置服务时会产生大量冗余 - 我们仍然手动列出所有内容.

但是,如果需要在多个不同的控制器中多次使用相同的服务,那么创建组合服务至少可以避免在每个控制器中列出一堆参数.

它比第一个解决方案更明确,并且允许您清楚地枚举您想要的服务,而不是在Angular的内部进行混乱,并允许您扩展服务,添加辅助/包装函数等.