一个控制器中的angularJS http回调函数修改了其他控制器的范围

时间:2015-04-02 03:31:50

标签: angularjs callback controller scope server-sent-events

我正在尝试将应用程序从纯JS转换为AngularJS,并遇到了一个问题,我将其解压缩到以下代码snipet中。

我有两个控制器,每个控制器都调用一个SSE服务器,每个控制器都有自己的回调函数。我的理解是每个控制器的$ scope不同,修改一个不会影响另一个。

但是,每当执行eventBCtrl中的eventBCallBack()时,它似乎会影响eventACtrl的$ scope。每当执行eventBCallBack()时,都会执行在eventACtrl中调用的过滤器。即使eventBCallBack()是一个空函数,它也没有区别。

我怀疑它与$ scope有关。$ apply。

以下是HTML文件:

<!DOCTYPE html>
<html ng-app="testApp">
<body>
  <div ng-controller="eventACtrl">
  <div>{{day}}</div>
  <lable for="filteredName">Filter:</label>
  <input type="text" name="filteredName" ng-model="filteredName"/>
  <table>
    <tbody>
        <tr ng-repeat="module in modules | matchFilter:filteredName | orderBy: 'name'">
            <td>{{$index+1}}</td>
            <td>{{module.name}}</td>
        </tr>
    </tbody>
  </table>
  </div>
  <div ng-controller="eventBCtrl">
  {{cpu}}
  </div>
  <script src="js/angular.min.js"></script>
  <script src="js/chaos.js"></script>
</body>
</html>

以下是javascript代码:

var testApp = angular.module("testApp", []);
testApp.controller("eventACtrl", function($scope) {

    var eventACallback = function(e) {
        $scope.$apply(function() {
        var pData = JSON.parse(e.data);
        var sDate = new Date(Number(pData.date));
        $scope.day = sDate.toDateString() + " " + sDate.toLocaleTimeString();
        $scope.modules = pData.modules;
        console.log("EVENTA");
        });
    }

    var source = new EventSource("http://" + location.host +"/EVENTS:A");
    source.addEventListener("EVENTA", eventACallback, false);
});

testApp.controller("eventBCtrl", function($scope) {

    var eventBCallback = function(e) {
        $scope.$apply(function() {
            var pData = JSON.parse(e.data);
            $scope.cpu = pData.cpu;
            console.log("EVENTB");
        });     
    }

    var source = new EventSource("http://" + location.host + "/EVENTS:B");
    source.addEventListener("EVENTB", eventBCallback, false);
});


testApp.filter("matchFilter", function() {
    return function(modules, filteredName) {
        console.log("filter: " + filteredName);
        var newModules = [];
        for (var i in modules) {
            if (modules[i].name.search(filteredName) != -1) {
                newModules.push(modules[i]);
            } else
                continue;
        }
        return newModules;
    };
});

2 个答案:

答案 0 :(得分:0)

根据您的描述,控制器A所具有的范围不会以任何方式“修改”,对吧?没有为该范围分配新模型或更改了这些模型的值。

所有发生的事情都是你的过滤器被执行了。这是预期的 - 无论摘要是如何启动的,都会在每个摘要周期执行一个数组过滤器。

这是一种使用$scope.$applyng-if创建新的子范围)时没有任何控制器或异步函数来重现问题的较小方法

<div ng-if="true" ng-init="items = [1, 2, 3]>
  <div ng-repeat="item in items | doNothing">{{item}}</div>
</div>
<button ng-click="">clicking me triggers digest</button>

doNothing这是:

.filter("doNothing", function(){
  return function(arr){
    console.log(arr);
    return arr;
  }
});

答案 1 :(得分:-1)

在这里和其他论坛上发布问题非常有帮助。我现在清楚地理解了这个问题,并制定了解决方案。

首先,$ scope。$ apply适用于根范围。这意味着即使我有单独的控制器,$ apply也会触发所有$ scope对象的观察者,而不仅仅是调用$ apply的控制器。

解决方案是从回调函数中删除$ scope并从函数中调用$ digest。这样,$ digest只会影响当前范围。

如下:

testApp.controller("eventBCtrl", function($scope) {

    eventBCallback = function(e) {
            var pData = JSON.parse(e.data);
            $scope.cpu = pData.cpu;
            $scope.$digest();
            console.log("EVENTB");
    }

我对此进行了测试,但效果很好。