我有两个模块的应用程序:
angular.module('components', []).directive('foo', function () { return {};});
angular.module('gaad', ['components']);
这个模块有很多指令,我不在这里。
该应用程序工作正常。但是,当我尝试检索模块gaad
的注入器时:
var injector = angular.injector(['gaad', 'components']); //called after 'gaad' module initialization
抛出错误:
Uncaught Error: Unknown provider: $compileProvider from components
现在应用程序非常大,我不知道我应该在哪里寻找bug。 所以我的问题是:我的问题可能是什么原因?
修改 我能够复制我的问题:http://jsfiddle.net/selbh/ehmnt/11/
答案 0 :(得分:120)
在回答问题之前,我们需要注意每个应用程序只有一个只有一个注入器实例而不是每个模块。从这个意义上说,不可能为每个模块检索一个注射器。当然,如果我们采用顶级模块,它代表整个应用程序。从这个意义上说,应用程序和顶级模块似乎是等价的。这似乎是一个微妙的差异,但重要的是要理解,以便充分和正确地回答这个问题。
接下来,根据我的理解,您希望检索 $injector
,而不是创建它的新实例。问题是angular.injector
将为指定为参数的模块(应用程序)创建一个新的$injector
实例。这里必须明确指定主要的AngularJS模块(ng)。所以,在这个代码示例中:
var injector = angular.injector(['gaad', 'components']);
您尝试使用'gaad'和'components'模块中定义的组件创建新的注入器,显然$compileProvider
未在自定义模块中定义。 将ng
模块添加到列表中会通过创建新的注入器来“解决”问题 - 这可能是您不希望发生的事情。
要实际检索与正在运行的应用程序关联的注射器实例,我们可以使用2种方法:
$injector
实例:http://docs.angularjs.org/api/angular.injector angular.element([DOM element]).injector()
,其中[DOM元素]是定义ng-app
的圆顶元素(或此元素的任何子元素)。更多信息:http://docs.angularjs.org/api/angular.element 以下是jsFiddle,显示了2个注入器检索方法:http://jsfiddle.net/xaQzb/
请注意,直接使用$injector
并不是单元测试之外的常见情况。从AngularJS世界之外检索AngularJS服务可能是有用的。更多信息:Call Angular JS from legacy code。
答案 1 :(得分:13)
您似乎还需要在进样器中包含ng。
var injector = angular.injector(['ng', 'b', 'a']);
必须明确添加ng模块。
答案 2 :(得分:2)
问题在于Angular代码的执行流程。要集成@pkozlowski.opensource的答案和相关注释,请注意在执行模块代码后,$injector
属性可供DOM元素使用,以便在您访问属性时(如同您尝试{{1它)该属性仍为console.log
。
您可以通过简单地为执行日志记录功能设置0超时来解决此问题(即,不需要以毫秒为单位的显式延迟)。这个hack是有效的,因为当堆栈为空时,就会执行日志记录功能,即当Angular的引导完成并且undefined
属性可用于DOM元素时。
Angular的术语中的另一个(可能更好)解决方案是将$injector
- 访问代码包含在run block中(另请参阅related API)。然后可以将$injector
作为普通服务轻松注入初始化函数。这是有效的,因为当所有引导终止时,运行块被排队并异步执行。
下面你可以找到两个小提琴,每个解决方案一个。
此外,通常无需显式加载$injector
模块。在正常情况下,ng
模型已经自动加载,除非您想要执行Angular代码的手动引导。其中一个答案中引用的文档(隐含地,不幸地)指向Angular的手动引导过程,当您必须手动创建注入器并告诉它要加载哪些模块时