【问题标题】:Dependency not injected although service exists尽管存在服务,但未注入依赖项
【发布时间】:2015-05-03 04:34:46
【问题描述】:

所以我一直在研究一个将在比赛中使用的 Angular.js 项目,并且在进行到一半时我意识到我需要一个插件系统来在运行时动态加载一些必要的代码。到目前为止,我发现 angular.js 不太适合在运行时加载服务。由于代码仅在比赛期间提供给竞争对手,我只能提供一个不起作用的示例。

// ex1.coffee

mainModule = angular.module('mainModule')

mainModule.service('needed', () ->
    @neededFunc() ->
        console.log "just an example"
    return this    

mainModule.service('ex1', ($injector) ->
    @loadFile = (u, pluginName) ->
        $.ajax
            dataType: "script",
            url: u,
            data: null,
            success: (jqxhr, textStatus) =>
                $injector.invoke([pluginName, (plugin) =>
                    plugin.testFunc()
            error: (jqxhr, textStatus, errorThrown) ->
                console.log "couldn't find the script"
    return this


// ex2.coffee

mainModule = angular.module('mainModule')

mainModule.service('ex2', (needed) ->
    @testFunc = () ->
        needed.neededFunc()
        console.log "in this dynamically loaded file"
    return this  

隐含的东西:有一个名为 mainModule 的现有模块。 jquery 和 angular 之前已经包含在 dom 中。 ex1.js 已经包含在 dom 中,而 ex2.js 尚未包含在 dom 中。 u 是文件 ex2.js 和 pluginName = "ex2" 的 URL。当调用成功处理程序时,调用函数失败,表示 ex2Provider 不存在。但是,如果我在成功回调中设置断点并检查 mainModule._invokeQueue,确实存在一个服务名称为“ex2”的数组,因此它在模块中肯定有一个现有的配方,但 $injector.invoke 调用仍然失败。如果我修改成功处理程序以调用 $injector.has pluginName,它会失败。有人能告诉我模块如何知道这个动态加载的服务的提供者,但不能用 $injector 将它注入到函数调用中吗? 该项目是一个用 grunt 构建的 yeoman 项目。

仍在学习 Angular,所以如果我遗漏了一些概念或说错了,请告诉我。

【问题讨论】:

  • 您确定丢失的是 ex2Provider 吗?通常 AngularJS 将依赖错误作为一个链给出,人们通过假设链中的第一个引用是触发错误的原因而误读了错误。
  • 基于示例。 ex2 将失败是依赖 needed 不存在。这会导致 ex2Provider 注入失败。
  • @MathewFoscarini - 在 ajax 加载 ex2.js 时,ex1.js 已经运行,因此需要并且 ex1 应该已经存在(至少作为配方)在 mainModule 中。每当我尝试将 ex2 注入该函数时,如果它以前不存在,它是否也不应该实例化并注入需要,或者如果它已经被实例化则只注入?在该成功处理程序中,我确认所有 3 项服务都存在配方。如果配方尚未实例化,$injector.has 或 $injector.invoke 是否会抛出异常?如果是这样,我可以手动实例化服务吗?

标签: jquery angularjs node.js coffeescript yeoman


【解决方案1】:

AngularJS 将在加载模块时引导它。在引导期间,所有依赖项都由注入器初始化。

angular.module('mainModule').service('ex2', .....);

当您通过 AJAX 执行上述操作时,它发生在 之后,mainModule 已经被引导。 service() 会将提供程序排队以进行引导,但引导永远不会再次发生。

这是来自引导角度的手册。

您应该在加载或定义模块后调用 angular.bootstrap()。您不能在应用程序引导后添加控制器、服务、指令等。

我认为您可以做的是创建一个新模块,并将其附加到现有模块。

所以您的 AJAX 代码可能如下所示。

angular.module('ex2Module',[]).service('ex2', .....);
angular.module('mainModule').requires.push('ex2Module');
$rootScope.$digest();

我无法对此进行测试,但我认为这将导致新模块 ex2Module 被引导并添加为现有 mainModule 的依赖项。注入器应该看到这个模块排队等待引导并安装它。

希望这会有所帮助。

【讨论】:

  • 明白了,我一直在挖掘文档,寻找确切说明的内容。但是,我不知道您可以像这样附加模块,绝对值得一试。现在没电了,等我能拿到代码的时候再试试。
  • 我很有希望,但这会产生相同的结果,角度会抛出一个异常,说 Unknown provider: ex2Provider
  • @FatalCatharsis 我在 Github 上找到了一个用于延迟加载模块和指令的项目。也许这会提供一些线索。 github.com/nikospara/angular-require-lazy
猜你喜欢
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
  • 2020-09-09
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多