Angularjs Can';t将喷油器从角度上收回

Angularjs Can';t将喷油器从角度上收回,angularjs,Angularjs,我的应用程序有两个模块: angular.module('components', []).directive('foo', function () { return {};}); angular.module('gaad', ['components']); 有一系列与这个模块相关的指令,我在这里不包括这些指令。 该应用程序运行良好。但是,当我试图检索模块gaad的喷油器时: var injector = angular.injector(['gaad', 'components']); /

我的应用程序有两个模块:

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。 所以我的问题是:我的问题的原因是什么?

编辑:
我能够复制我的问题:

看来您还需要在喷油器中加入ng

var injector = angular.injector(['ng', 'b', 'a']);
发件人:

必须显式添加ng模块


在回答问题之前,我们需要注意每个应用程序只有一个喷油器实例,而不是每个模块。从这个意义上讲,不可能检索每个模块的喷油器。当然,如果我们使用顶级模块,它代表了整个应用程序。从这个意义上讲,应用程序和顶级模块似乎是等价的。这似乎是一个微妙的区别,但为了全面、正确地回答这个问题,理解这一点很重要

接下来,据我所知,您希望检索
$injector
,而不是创建它的新实例。问题是
angular.injector
将为指定为参数的模块(应用程序)创建一个新的
$injector
实例。这里必须明确指定主AngularJS模块(ng)。因此,在这个代码示例中:

var injector = angular.injector(['gaad', 'components']);
您试图从“gaad”和“components”模块中定义的组件创建新的注入器,显然,
$compileProvider
未在自定义模块中定义
ng
模块添加到列表将通过创建新喷油器来“解决”问题
——这可能是您不希望发生的事情

要实际检索与正在运行的应用程序关联的注入器实例,我们可以使用两种方法:

  • 在AngularJS JavaScript中,最简单的解决方案就是注入
    $injector
    实例:
  • 从AngularJS世界之外-调用
    angular.element([DOM element]).injector()
    其中[DOM element]是定义
    ng app
    的圆顶元素(或此元素的任何子元素)。更多信息请点击此处:
下面是JSFIDLE,它显示了两种检索喷油器的方法:


还请注意,在单元测试之外,直接使用
$injector
不是很常见的场景。对于从AngularJS世界之外检索AngularJS服务来说,这可能是一个有用的想法。这里有更多信息:。

问题在于Angular代码的执行流程。要在@pkozlowski.opensource的答案和相关注释上集成,请注意执行模块代码后,
$injector
属性对DOM元素可用,因此当您访问该属性时(就像尝试
console.log
它时),该属性仍然是
未定义的

您可以通过简单地为日志功能的执行设置0超时来解决此问题(即,不需要以毫秒为单位的显式延迟)。这种方法之所以有效,是因为日志函数将在堆栈为空时执行,即Angular的引导完成并且DOM元素可以使用
$injector
属性时执行

Angular术语中的另一个(也许更好)解决方案是将您的
$injector
-访问代码包含在一个数据库中(另请参见)。然后,
$injector
可以作为正常服务轻松地注入初始化功能。这是因为当所有引导终止时,运行块将排队并异步执行

下面您可以找到两个小提琴,每个解决方案一个

编辑
此外,通常不需要显式加载
ng
模块。在正常情况下,
ng
模型已自动加载,除非您希望手动引导Angular的代码。其中一个答案中引用的一段文档(不幸的是隐式地)提到Angular的手动引导过程,当您必须手动创建注入器并告诉它您要加载哪些模块时

顺便说一句,如果您使用ng app,您不需要创建应用程序注入器。听到这个@maxisam很高兴!通过回答这些问题,我学到了很多:-)您发布的JSFIDLE返回
未定义的
作为注入器。。。如果您
console.log(injector)
它将返回
undefined
。这是伪代码吗?显然喷油器的可用性有一些延迟。如果你把它放在一个超时,你得到的注入器刚刚好。。。有趣。请看这里:。。。我不知道为什么会这样,我仍然没有找到延迟是什么。@blesh,是的,是伪代码,也许我不应该发布JSFIDLE。。。时间问题源于AngularJS需要时间来提升应用程序并在DOM元素上公开注入器。我将更改JSFIDLE并添加您的示例thnx!!!