设置多个观察者以激发动态事件的角度,替代解决方案 - 优化的观察者模式

时间:2015-03-10 13:29:39

标签: javascript angularjs observer-pattern

所以我有一个工厂设置为观察URL更改,然后触发并更改控制器中的范围变量,以便在URL更改时更新它们。基本的想法是我有一个URL对象我存储,它将信息发送到不同的模块来控制它们的状态。这样,如果您愿意,用户可以复制/加入URL并保存状态。

所以我现在拥有的是每个由此控制的控制器中的每个范围变量。它工作得很好,但是我遇到的问题是,如果我(可能)在网址中有90个不同的状态,那就是90个观察者,每当我更改网址时,该功能会触发90次,而最有可能只需要它解雇他们中的一个或两个。

现在这是代码 -

工厂:

 .factory('urlWatch', function(urlFactory) {
    return {
        listenToUrl: function(scope, moduleName, stateName, bindTo) { 
            //create closure for binding a watch to specific scope on controller
            scope.$on('$locationChangeSuccess', function(event) {
                //parseState just checks if it's an acceptable state
                scope[bindTo] = urlFactory.parseState(moduleName, stateName);
            });
        }
    };

});

在控制器中,我会做类似的事情:

//set initial state
$scope.mod1m1 = urlFactory.parseState("module1", "mod1");
//hook onto url listener
urlWatch.listenToUrl($scope, "module1", "mod1", "mod1m1");

所以,现在我在2个不同的控制器中有这个,每个2个范围,所以每次范围。$ on(' $ locationChangeSuccess')触发时,它会发送给所有4个。

我想弄清楚的是,如果有一种方法可以优化它,那么它只会发送它所需要的东西。我可以保持" 1回来" url对象的版本很容易检查已更改的内容并可能将其包装在条件中?

假设我可以访问已更改的内容,例如,我可以执行此类操作吗?

.factory('urlWatch', function(urlFactory) {
    return {
        listenToUrl: function(scope, moduleName, stateName, bindTo, whatsChanged) { 

            scope.$on('$locationChangeSuccess', function(event) {
                 if(whatsChanged == moduleName[stateName]){
                //parseState just checks if it's an acceptable state
                scope[bindTo] = urlFactory.parseState(moduleName, stateName); }
            });
        }
    };

});

检查更改的url项是否与当前项(moduleName [stateName])匹配,如果是,则触发。我不确定这是否是接近这一点的最佳方式。我正在寻找一个优化的观察者模式。

我正在努力解决的问题是如何正确设置它,并且肯定可以在这个问题上使用一些输入。感谢您抽出宝贵时间阅读!

1 个答案:

答案 0 :(得分:0)

如果我正确地解决了您的问题,那么从我的角度来看,最好的方法是将您的urlWatcher工厂更改为全局单件服务,并仅在此工厂内对路由更改事件做出响应。工厂将保持当前路线参数,并且每个控制器可以根据它们检查这些参数和设置。全球服务可能如下所示:

app.service("routeWatcher", function (){
  var service={};

  service.watchFunction=function (event, data){
    service.currentRouteParams=data.params;
  };

  return service;
}])

全局使用(服务是按需创建的,因此我们需要在启动时实例化它):

.run(function ($rootScope, routeWatcher){
  $rootScope.$on('$routeChangeSuccess',routeWatcher.watchFunction);
})

然后,任何需要根据路线参数进行设置的控制器都可以从单点获取此值:

app.controller("test1", function ($scope, routeWatcher){
  /*I need to get my specific route params here*/
  $scope.param=routeWatcher.currentRouteParams["param"];
})

这是我的plunker,第一个视图/控制器使用路由http://plnkr.co/edit/NbDoCgt71xPAZgKaSxwi?p=preview

中的参数