访问可能存在或不存在的Angular服务

时间:2016-06-07 15:15:10

标签: javascript angularjs

我正在设计一个非常模块化的Angular项目 - sections of the app can be enabled and disabled for different clients using Webpack.这个结构对我来说效果很好,但我遇到的一个问题是如何处理可能并不总是存在的服务。

我当前的解决方案非常简单 - 我使用$injector.has()检查服务当前是否存在,如果是,我使用$injector.get()来抓取它:

function initialize($injector) {
    if ($injector.has("barcode")) {
        let barcode = $injector.get("barcode");

        // Do stuff with the barcode service
    }
}

这似乎有效 - 但是,我找不到关于这种模式的使用的信息,以及它是否有任何潜在的缺点。

所以,我的问题是:

  • 我应该注意使用注射器吗?
  • 这样做有更好/更惯用的方法吗?

1 个答案:

答案 0 :(得分:2)

这可能是达到你想要的最佳方式;但是,在执行此操作时,请注意您正从 Dependency Injection (DI)转移到 Service Locator 模式。

以下from the Angular 2 docs非常重要(强调我的):

  

我们避免使用这种技术,除非我们真正需要它。它鼓励像我们在这里看到的粗心的抓包方法。很难解释,理解和测试。我们无法通过检查构造函数来了解这个类需要什么或它将做什么。它可以从任何祖先组件获取服务,而不仅仅是它自己的组件。我们不得不通过实施来发现它的作用。

     

当框架开发人员必须通用且动态地获取服务时,可采用此方法。

(旁白:值得阅读dependency injection in Angular 2即将发生的事情 - 可选的依赖项,工厂提供商等。)

Angular 1的docs on the matter引用它The Law of Demeter(这当然更像是一条指导而不是法律,对吧?)。

无论如何,还需要注意一些其他事项:

  • 您将不会被警告(通过errors thrown)循环依赖关系使用它;事实上,这通常是人们用来解决这些警告的技术。

  • 由于您现在除了注入的内容之外还依赖于$ injector,因此您的单元测试需要模拟$ injector,或使用类似module('moduleThatIsUsingInjectorExplicitly', function($provide) { $provide.value('barcode', barCodeMock);}的内容。

    < / LI>
  • 正如上面的引文中所提到的,由于这些“可选”的依赖关系并未在通常的地方定义,因此您的代码将不那么明确。

很多其他关于服务定位器模式的读数,并将其与DI进行对比。有趣的是,但对我们的实际意义可能有限,特别是因为JavaScript缺乏Interface / Abstract和Angular 1的DI实现意味着实际的差异点较少。