AngularJS中的循环依赖和OOP问题

AngularJS + OOP是一个性感的function使用

嗨,我成功地使用OOP与AngularJs已经有一段时间了(首先与行动中的OOPinheritanceangularjs开始),提供的方法允许您定义您的类为angular度服务,您可以稍后扩展或inheritance像这样:

Application.factory('AbstractObject', [function () { var AbstractObject = Class.extend({ virtualMethod: function() { alert("Hello world"); }, abstractMethod: function() { // You may omit abstract definitions, but they make your interface more readable throw new Error("Pure abstract call"); } }); return AbstractObject; // You return class definition instead of it's instance }]); Application.factory('DerivedObject', ['AbstractObject', function (AbstractObject) { var DerivedObject = AbstractObject.extend({ virtualMethod: function() { // Shows two alerts: `Hey!` and `Hello world` alert("Hey!"); this._super(); }, abstractMethod: function() { alert("Now I'm not abstract"); } }); return DerivedObject; }]); 

Plunker: http ://plnkr.co/edit/rAtVGAsNYggBhNADMeoT

使用描述的方法使您能够定义完美集成到angular度基础结构中的类。 你可以从两个世界获得各种漂亮的function – OOP和AngularJs。 dependency injection对你的类是免费的,它使你的类变得简单,允许将许多样板控制器代码放入一些基类中,以便以后重用。

然而

先前描述的AngularJs基础设施模块的所有方法都是100%展开翅膀。 当您尝试定义recursion类定义(即recursion聚合)时会出现问题,例如您有两个类定义,如BlogTag

 Application.factory('Blog', ['Tag', function (Tag) { var Blog = Class.extend({ tags: function() { return this.tags; } }); return Blog; }]); Application.factory('Tag', ['Blog', function (Blog) { var Tag = Class.extend({ Blogs: function() { return this.blogs; } }); return Tag; }]); 

它不会工作,因为BlogTag自我引用自己造成循环依赖。

PS

最后一件事,我发现有一个丑陋的解决scheme,在我的具体情况下解决了我的问题,但是一般情况下并不奏效,正如我所说的那样:

 Application.factory('BlogNamespace', [function () { var Blog = Class.extend({ tags: function() { return this.tags; } }); var Tag = Class.extend({ Blogs: function() { return this.blogs; } }); return { Tag: Tag, Blog: Blog }; }]); 

上述修补程序将不起作用,因为名称空间也可能是循环依赖的主题。 这意味着现在解决问题并不是解决scheme,而是一个更深层次的问题。

关于在一般情况下如何解决所描述的问题的任何build议?

循环依赖总是混合关注的标志,这是一件非常糟糕的事情。 AngularJS的作者之一MiškoHevery 在他的博客上解释了一个很好的解决scheme。 总之,你可能有第三个服务隐藏在某个地方,这是你的代码中唯一真正需要的部分。

我正在回答自己的问题,只是因为我find了解决我最初发布的问题的技术方法。 但在此之前,我强烈build议您使用Blackhole的build议,因为它可以解决通常由于糟糕的架构造成的更广泛的问题。 请首先使用他的方法,并返回到当前的方法,以防你知道你在做什么。

所以在这里:

您可以使用$injector服务并在运行时注入所需的定义,从技术angular度来看这是合法的,但是根据这个post(很难想象它是在2008年写的),这就像一个黑魔法,做这将会打击你:

 Application.factory('Blog', ['$injector', function ($injector) { var Tag = $injector.get('Tag'); // Here is your tag ... }]); Application.factory('Tag', ['Blog', function (Blog) { ... }]); 

编辑

事实certificate,目前的方法是Service Locator模式的一个例子,即IoC Antipattern。

最后的度假村:不鼓励

在我的情况下,解决循环依赖问题的最好方法就是通过$rootScope -broadcasts触发函数调用 。 然后另一个服务可以收听这个广播,并对所需的function调用做出反应。 这可能不是最优雅的解决scheme,但在某些情况下,服务之间的交互主要是单向的,这可能是一个合理的select。 (请注意,这也只允许通过callback函数将返回值传回给广播函数)


一个假的例子是:

 angular.module('myApp').factory('service1', ["$rootScope", function($rootScope) { function func1() { // do something } $rootScope.$broadcast("callFunc2"); // calls func2 from service 1 return { func1: func1 } } ]); angular.module('myApp').factory('service2', ["service1", "$rootScope", function(service1, $rootScope) { function func2() { // do something } service1.func1(); // calls func1 from service 2 $rootScope.on("callFunc2", func2); } ]);