代码之家  ›  专栏  ›  技术社区  ›  AlexD

AngularJS$watch-无限循环

  •  3
  • AlexD  · 技术社区  · 11 年前

    我有两个日期-开始和结束。我想验证(并重新保证)启动<终止 我收到了他们使用$watch进行更改的通知,然后我去更改它们以确保满足条件,但随后它再次触发$watch,然后我得到了$digest的最大迭代次数,事情就开始了。

    所以我的问题是-我如何改变在 $watch 而不会导致无限循环。(除了进行更多检查并仅在实际需要更改时进行更改)

    这是我的代码:

    var TIME_DAY = 1000 * 60 * 60 * 24;
    
    $scope.$watch('timeFilter.startTime', function () {
        validateStartEndTime();
    },true);
    
    $scope.$watch('timeFilter.endTime', function () {
        validateStartEndTime();
    },true);
    
    function validateStartEndTime() {
        if ($scope.timeFilter.startTime != null && $scope.timeFilter.endTime != null) {
            // Remove all seconds
            if ($scope.timeFilter.startTime.getSeconds() > 0)
                $scope.timeFilter.startTime.setSeconds(0);
            if ($scope.timeFilter.endTime.getSeconds() > 0)
                $scope.timeFilter.endTime.setSeconds(0);
            if ($scope.timeRange.minTime.getSeconds() > 0)
                $scope.timeRange.minTime.setSeconds(0);
            if ($scope.timeRange.maxTime.getSeconds() > 0)
                $scope.timeRange.maxTime.setSeconds(0);
    
            // When start time isn't before end time
            if ($scope.timeFilter.startTime >= $scope.timeFilter.endTime) {
                // We want to increase end time by 1 minute, if possible - do it. Else - reduce start time by 1 minute
                if ($scope.timeFilter.endTime < $scope.timeRange.maxTime) {
                    $scope.timeFilter.endTime.setMinutes($scope.timeFilter.startTime.getMinutes() + 1);
                } else {
                    $scope.timeFilter.startTime.setMinutes($scope.timeFilter.startTime.getMinutes() - 1);
                }
            }
    
            // Start time before min time
            if ($scope.timeFilter.startTime < $scope.timeRange.minTime) {
                $scope.timeFilter.startTime = $scope.timeRange.minTime;
                if ($scope.timeFilter.endTime <= $scope.timeFilter.startTime) {
                    $scope.timeFilter.endTime = $scope.timeFilter.startTime;
                    $scope.timeFilter.endTime.setMinutes($scope.timeFilter.endTime.getMinutes() + 1);
                }
            }
    
            // End time after max time
            if ($scope.timeFilter.endTime > $scope.timeRange.maxTime) {
                $scope.timeFilter.endTime = $scope.timeRange.maxTime;
                if ($scope.timeFilter.startTime >= $scope.timeFilter.endTime) {
                    $scope.timeFilter.startTime = $scope.timeFilter.endTime;
                    $scope.timeFilter.startTime.setMinutes($scope.timeFilter.startTime.getMinutes() - 1);
                }
            }
        }
    }
    
    2 回复  |  直到 11 年前
        1
  •  1
  •   Daniele    11 年前

    老实说,我更希望找到一种方法来避免改变一个经常被监视的变量。但是,如果你真的想要,你可以在你必须改变被监视的变量时注销你的$watch函数,然后重新注册$watch功能。

    要注销$watch函数,只需获取引用并在需要时调用即可。

    var myWatch = $scope.$watch('timeFilter.startTime', function () {
       validateStartEndTime();
    },true);
    myWatch(); // It will deregister it.
    

    请记住,有时当您第一次观察变量时,它会自动触发函数。我的建议是始终检查旧变量是否真的更改了。

    var myWatch = $scope.$watch('timeFilter.startTime', function (newValue, oldValue) {
       if(newValue === oldValue){
          return;
       }
       validateStartEndTime();
    },true);
    

    我希望它对你有用。不幸的是,我现在无法测试此代码。

        2
  •  0
  •   AlexD    11 年前

    我综合了每个回复类似问题的人的建议和建议:

    $scope.$watch('timeFilter.startTime', function(newValue, oldValue) {
        if (newValue === oldValue) return;
        validateStartEndTime();
    }, true);
    
    $scope.$watch('timeFilter.endTime', function(newValue, oldValue) {
        if (newValue === oldValue) return;
        validateStartEndTime();
    }, true);
    
    function validateStartEndTime(startChanged) {
        if ($scope.timeFilter.startTime == null || $scope.timeFilter.endTime == null) return;
        var tempStart = new Date($scope.timeFilter.startTime), tempEnd = new Date($scope.timeFilter.endTime);
        if ($scope.timeRange.minTime && $scope.timeRange.maxTime) {
            // Logic start
    
            // Logic ends
    
            if ($scope.timeFilter.startTime !== tempStart)
                $scope.timeFilter.startTime = tempStart;
            if ($scope.timeFilter.endTime !== tempEnd)
                $scope.timeFilter.endTime = tempEnd;
        }
    }
    

    通过这种方式,我确保我尽可能少做改变。如果有人提出任何建议,我愿意接受