Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/446.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript AngularJS中的循环依赖和OOP问题 AngularJS+OOP是一种性感的功能_Javascript_Oop_Angularjs - Fatal编程技术网

Javascript AngularJS中的循环依赖和OOP问题 AngularJS+OOP是一种性感的功能

Javascript AngularJS中的循环依赖和OOP问题 AngularJS+OOP是一种性感的功能,javascript,oop,angularjs,Javascript,Oop,Angularjs,您好,我已经成功地将OOP与AngularJs结合使用了一段时间(首先从开始),所提供的方法允许您将类定义为angular服务,稍后您可以这样扩展或继承: Application.factory('AbstractObject', [function () { var AbstractObject = Class.extend({ virtualMethod: function() { alert("Hello world"); },

您好,我已经成功地将OOP与AngularJs结合使用了一段时间(首先从开始),所提供的方法允许您将类定义为angular服务,稍后您可以这样扩展或继承:

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;
}]);
普朗克:

使用所描述的方法,您可以定义漂亮地集成到angular基础结构中的类。您可以从两个世界获得各种漂亮的特性—OOP和AngularJs。依赖项注入对您的类是免费的,它使您的类变得简单,允许将大量样板控制器代码放入一些基类中,以便以后重用

然而 AngularJs基础设施阻止了之前描述的方法在所有100%的基础上扩展它的翅膀。当您试图定义递归类定义(即递归聚合)时,会出现问题,例如您有两个类定义,如
Blog
Tag

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;
}]);
它不起作用,因为
Blog
Tag
都是自引用,导致循环依赖

附笔 最后一件事,我找到了一个丑陋的解决方案,它解决了我在具体案例中的问题,但总体上不起作用,正如我所说,它不漂亮:

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
    };
}]);
问题: 由于名称空间也可能是循环依赖的主题,因此上述修复无法工作。这意味着它不是所描述问题的解决方案,而是一个更深层次的问题


对于如何在一般情况下解决所描述的问题,有什么建议吗?

循环依赖始终是混合关注点的标志,这是一件非常糟糕的事情。AngularJS的作者之一Miško Hevery解释了一个很好的解决方案。简而言之,您可能在某个地方隐藏了第三个服务,这是您的代码中其他两个真正需要的唯一部分。

我回答自己的问题,只是因为我找到了一种技术方法来解决我最初发布的问题。但在此之前,我强烈建议您使用Blackhole的建议,因为它允许解决通常由糟糕的体系结构引起的更广泛的问题。请先使用他的方法,如果你知道你在做什么,请回到当前的方法

下面是:

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

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

    ...    
}]);

Application.factory('Tag', ['Blog', function (Blog) {
    ...
}]);

编辑
事实证明,当前的方法是服务定位器模式的一个例子,它是IoC反模式。

最后的手段:不鼓励

在我的例子中,最好的方法是通过
$rootScope
-broadcasts
触发函数调用,以避免像angular中这样的循环依赖性问题。然后,另一个服务可以收听此广播并对所需的函数调用作出反应。它可能不是最优雅的解决方案,但在某些情况下,服务之间的交互主要是单向的,它可能是一个合理的替代方案。(请注意,这还允许仅通过回调将返回值传递回广播函数)


这方面的一个伪例子是:

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);
  }
]);

Blackhole,这是你提供的非常有趣的帖子,我用
Tag
Blog
证明了Misko是对的,因为这些是一种数据库实体,它们之间以N:M的形式相互关联,在关系数据库世界中,这种情况也可以通过表示第三个关系表来解决,第三个关系表同时引用
Tag
Blog
,比如
BlogTags
,到目前为止还不错。。。飞行是稳定的,描述的方法确实有助于识别有问题的实现点。我认为你的方法是正确的,在代码中使用循环DEP是一件坏事,所以答案是you@Lu4您是否通过添加一个
BlogTags
工厂来解决这个问题,该工厂将
Blog
Tag
注入其中?如果可以的话,我真的不想在我的代码库中添加“连接表”类。。。如果我唯一的另一个选择是使用
$injetor.get
循环依赖项,正如您所指出的,我可能会坚持这样做。是的,我有一个服务/模型,它需要从其他模型中获得一个计数(实际上是n个深层结构的层次映射),以生成“小部件”来显示数据。包含数据的所有业务逻辑都是独立的,但要生成绑定到这些模型的新小部件实例,我需要在生成元数据之前先查找元数据。。。我会觉得做$injector.get这个用例是安全的。这个答案救了我一天+1加入黑暗面:)@RodrigoQuesada你的建议是一个真正年轻而充满激情的开发人员的建议:)你遵循教条和范例真的很酷,这意味着你选择了自己的方式。然而,对我来说,这看起来很有趣,因为我已经太老了,无法跟上它。请不要把我的话当作侮辱,而是把它们当作经验的声音,你未来的声音。我有很多理由担心你的提议。其中一个事实是,我知道它们是由许多无辜开发人员的鲜血编写的。我不需要每个人都同意这个事实,我只需要聪明的人这不起作用,$injector就是从@whitebox开始报告循环依赖性的东西,它不适用于单元测试,但是如果你在模块首次初始化后使用它(例如,在模块中的函数中使用它),它可以正常工作。我认为Lu4在写答案时简化了情况,使之简短。@Lu4有任何建设性的批评吗?当我把我自己的问题的答案贴出来时,我认为我已经达到了“黑暗”的极限(我在评论中指的是“黑暗面”笑话),但是