【问题标题】:Can't retrieve the injector from angular无法从角度检索注射器
【发布时间】:2012-11-04 05:45:12
【问题描述】:

我的这个应用有两个模块:

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 

应用程序现在相当大,我不知道应该去哪里寻找错误。 所以我的问题是:我的问题可能是什么原因?

编辑: 我能够复制我的问题:http://jsfiddle.net/selbh/ehmnt/11/

【问题讨论】:

  • 顺便说一句,如果你使用ng-app,你不需要创建应用程序注入器。

标签: angularjs


【解决方案1】:

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

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

var injector = angular.injector(['gaad', 'components']);

您试图从“gaad”和“components”模块中定义的组件创建一个新的注入器,显然$compileProvider 没有在您的自定义模块中定义。 ng 模块添加到列表中将通过创建新的注入器来“解决”问题——这可能是您不希望发生的事情。

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

这里是 jsFiddle 展示了注入器检索的 2 种方法:http://jsfiddle.net/xaQzb/

还请注意,在单元测试之外,直接使用$injector 并不是很常见的场景。从 AngularJS 世界之外检索 AngularJS 服务可能是有用的想法。更多信息在这里:Call Angular JS from legacy code

【讨论】:

  • 很高兴听到这个@maxisam!通过回答这些问题,我学到了很多东西:-)
  • 您发布的 JSFiddle 返回 undefined 作为注入器。 jsfiddle.net/xaQzb ...如果你 console.log(injector) 它返回 undefined。它是伪代码吗?
  • 显然注射器的可用性有一些延迟。如果您将其设置为超时,则注射器会很好……很有趣。
  • 见这里:jsfiddle.net/blesh/xaQzb/6 ...我不知道为什么会这样,我还没有找到延迟是什么。
  • @blesh,是的,意味着是伪代码,也许我不应该发布 jsFiddle... 时间问题来自 AngularJS 需要时间来提升应用程序并暴露注入器一个 DOM 元素。我将更改 jsFiddle 并添加您的示例,thnx !!!
【解决方案2】:

看来您还需要在注入器中包含 ng。

var injector = angular.injector(['ng', 'b', 'a']);

发件人:AngularJS: injector

ng 模块必须显式添加。

【讨论】:

    【解决方案3】:

    问题在于 Angular 代码的执行流程。要集成 @pkozlowski.opensource 的答案和相关 cmets,请注意 $injector 属性在模块代码执行后可用于 DOM 元素,以便在您访问该属性时(就像您尝试 console.log 它时一样)该属性仍将是undefined

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

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

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

    0 Timeout jsFiddle

    Run block jsFiddle

    编辑

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

    【讨论】:

      猜你喜欢
      • 2018-06-14
      • 2016-12-04
      • 1970-01-01
      • 1970-01-01
      • 2018-09-19
      • 1970-01-01
      • 2020-10-27
      • 2020-08-15
      • 2019-08-13
      相关资源
      最近更新 更多