1

我继承了一些使用全局对象来存储角度服务的代码。这些服务通过角度模块的运行功能附加到全局对象。我的问题是,这是否会导致麻烦?测试造成了什么样的麻烦?像这样传递服务似乎比注入每个控制器中的所有服务容易得多,所以我明白了为什么这样做。没有这样做的其他理由是什么?下面是一些代码来说明我在说什么:使用全局对象避免角度依赖注入

// vars 
var globalObject = 
{ 
    ng: {}, 
}; 

// Setup module 
var myModule = angular.module("myModule", []); 
myModule.config(doStuff); 
myModule.run(setUpGlobals); 

// Setup app globals 
function setUpGlobals(ngRootScope, ngHttp, ngTimeout) 
{ 
    globalObject.rootScope = ngRootScope; 

    // angular services 
    globalObject.ng.http = ngHttp; 
    globalObject.ng.Timeout = ngTimeout; 
} 
setUpGlobals.$inject = ['$rootScope', '$http', '$timeout']; 

回答

1

模块和DI都是在Angular中引入的,以避免依赖全局和提高模块性。

这是天真的方法,只有在有单个模块和单个应用程序实例时才有效。如果有几个模块可以单独使用(包括测试),它将会失败。如果页面上有多个应用程序实例(例如,如果Angular用于非SPA应用程序),它会产生可怕的错误。

整体模块损害可测试性。即使这样使用,一些选项也是不可用的,例如,在$controller(...)中注入spied或stubbed服务 - 因为控制器依赖于全局变量。

setUpGlobals导致急切的服务实例化。这对核心服务来说可能不是问题,但对于现在不需要实例化的服务而言,这会是一个问题。

不太重要的问题是缩小应用程序中的代码大小。 ng.$rootScope可以缩小到a.$rootScope,但没有更多。注释函数应该提及'$rootScope'一次字符串,但$rootScope变量名可以缩小为a。如果服务在函数中多次使用,将会有所改进。

有很多原因why global variables are bad。其中一些在这种情况下将不适用,其他则会。

+0

谢谢!我不知道服务是按需实例化的。 https://www.bennadel.com/blog/2715-services-and-factories-are-instantiated-on-demand-in-angularjs.htm –

+1

不客气。大多数时候这不会是一个问题,但是这可能会破坏依赖于自然行为的功能,例如延迟加载。 – estus

+0

还有一个问题:服务在不同模块中扮演单身人士的角色吗?他们为同一模块做,但如果模块A和模块B注入服务1,服务1将被共享? –

1

这使得测试噩梦。依赖注入很棒,因为它意味着你可以通过嘲笑你不需要的服务来进行一些原子测试。在一个简单的,非参考性的例子中,设想一个通过http进行API调用的服务,如果你使用它,你的测试可以模拟出http并假装一个返回,让你只测试你想要的代码位,使您不必进行依赖API的测试,或者更糟糕的是使用API​​调用的测试套件。随着全球范围内的供应商,这是更难以实现的。

只是一个原因,我敢肯定还有很多其他的。

+0

实际上,测试不会那么糟糕 - 只要有一个模块,全局变量就会在每次测试中重新分配。但重要的是它并不一定是单一的。一旦没有,就会出现问题。 – estus