Angularjs 为什么我的观察者会因为同样的变化而被呼叫两次?

Angularjs 为什么我的观察者会因为同样的变化而被呼叫两次?,angularjs,angularjs-scope,angularjs-ng-repeat,Angularjs,Angularjs Scope,Angularjs Ng Repeat,我有一个AngularJS 1.4*应用程序在本地运行(还没有)。此应用程序由Laravel 5.1后端RESTFul API提供服务 我必须使这个应用程序,代表一个包旅行。包由天组成,从0到N天不等。每天都有一个服务列表,范围从0到N个服务。还有一家旅馆 我的web服务器是我的laravel应用程序使用的服务器,它向我提供了一个预先设置的包,其中包含一个日期列表:每个日期都有一个服务列表和一个酒店数据(到目前为止尚未使用)。在响应中,我有一个包的属性列表(暂时不重要)和一个天数数组,称为day

我有一个AngularJS 1.4*应用程序在本地运行(还没有)。此应用程序由Laravel 5.1后端RESTFul API提供服务

我必须使这个应用程序,代表一个包旅行。包由天组成,从0到N天不等。每天都有一个服务列表,范围从0到N个服务。还有一家旅馆

我的web服务器是我的laravel应用程序使用的服务器,它向我提供了一个预先设置的包,其中包含一个日期列表:每个日期都有一个服务列表和一个酒店数据(到目前为止尚未使用)。在响应中,我有一个包的属性列表(暂时不重要)和一个天数数组,称为
days\u info
。该响应被放入我的
PackageController
上的
$scope.package
PackageController还声明了一个名为
packageBlock
的指令,该指令包含一个天数列表以及包的一些其他数据

<div ng-repeat="day in package.days_info" class='row'>
    <div class='col-md-12'>
        <package-days-block></package-days-block>
    </div>
</div>
对于服务id更改,将在观察程序上调用
reloadServicesTable

// ServiceController
$scope.$watch(
    'service.service_id', // Places the watcher to watch the changes on the service's ID.
    function(new_service, old_service) {
        if( new_service === old_service )
            return; 

        $scope.reloadServicesTable($scope.service.service_id, $scope.service.service_day, $scope.day.date, $scope.package.paxes);

    }
);
问题从这里开始:当服务id只更改一次时,对服务表的请求被调用两次

为什么,上帝,为什么

还有我的代码的另一部分,我从PackageController运行整个
days\u info
数组,读取service.table:
service.table.price
中的属性
price
。在那里,我意识到有两个范围:一个是我处理的,另一个是我没有奇怪的想法它来自哪里

如果我放置一个
console.log($scope)
知道为什么会这样吗

附言:这是我的第一个AngularJS应用程序,所以,如果我在一些基本问题上搞砸了,请放心

编辑:

正如一位同事在评论中指出的那样,我的问题不是很容易重复。可悲的是,我不能把我怀疑的部分放在这里,因为我根本不知道问题出在哪里!(我知道这帮不了什么忙)

我在Chrome控制台上拍摄了一些屏幕截图:

首先,请求是在更改服务id时触发的

如您所见,每个请求每次调用两次。这不是一次性的事情。
/api/service/{id}…
是对服务表信息的调用。
/api/service/by_route/origin/…
返回从一个城市到另一个城市(或相同城市)的服务列表。一方不干涉另一方

另一个图像是更改服务id时从PackageController$scope的控制台.log输出的

正如你所看到的,有两个不同的作用域。而
b
范围是
r
范围的子范围。
r
作用域也在调用
服务id
上的观察者

如下图所示,从不同的地方调用了两次总价调用:


服务
向下传递到指令中。使用双向绑定将您的
日期
服务
更改传递回package.days\u信息

删除您的
ServiceController
重复一个控制器没有多大意义
是处理逻辑的E指令

在你的软件包中只写一个观察者Controller观察
软件包。days\u info
当你的
日期或
服务发生变化时,它可以简单地发现并采取措施


冷静下来,把它修好

它可能会解决您的问题。就连我也面临着与你提到的完全相同的问题

  • 对我来说,原因是,控制器正在重新初始化,其中编写了一个单独的api调用,用于最初加载页面

  • 也可能存在这样一种情况,即您在标记中已分配控制器两次


  • 您的问题太长,包含大量不相关的信息,但缺少可复制的测试用例。所以很难理解到底是什么问题。但是文档中说:*[…]在极少数情况下,这是不可取的,因为在watchExpression的结果没有改变时调用侦听器。要在侦听器fn中检测此场景,可以比较newVal和oldVal。如果这两个值相同(==),则由于初始化而调用侦听器。通常,使用手表是个坏主意。如果您以一种简单的方式告诉我们您想要实现的目标,我们可以帮助您找到更好的方法。我正在比较在compare函数后调用的fn中的两个值(newValue和oldValue)。这似乎不再是问题所在。因为函数被系统地调用了两次!我将从我的请求网络日志中打印两份内容,并在服务更改时显示一个请求的作用域。这只是瞎猜,但请确保ServiceController没有实例化两次。另外,你有大约8800名观察者,这在性能上是非常糟糕的。@DennisBraga你需要对这个问题做出回答,我查看了你在聊天中发布的内容,但是只有js代码。我认为不可能猜出你的设置有什么问题。需要一些调试才能找到问题。问题并不是那么简单。但是,小费很好!很不错的。因为从现在起我可能会使用它,所以我会给你赏金(因为它也会在22分钟后过期)。非常感谢。这正是发生在我身上的事!你有14秒没拿到赏金已经分配给罗伯特了。我为一个div定义了一个
    ng控制器
    ,并在同一个控件上调用了一个指令
    // ServiceController
    $scope.reloadServicesTable = function(service_id, service_day, date, paxes){
        MandatoryService.getServiceTable(service_id, service_day, date, paxes)
        .then(
            function(service_data) {
                $scope.service.table = service_data;
            }, 
            ...
        );
    
    // ServiceController
    $scope.$watch(
        'service.service_id', // Places the watcher to watch the changes on the service's ID.
        function(new_service, old_service) {
            if( new_service === old_service )
                return; 
    
            $scope.reloadServicesTable($scope.service.service_id, $scope.service.service_day, $scope.day.date, $scope.package.paxes);
    
        }
    );
    
    <div ng-repeat="day in package.days_info" class='row'>
        <div class='col-md-12'>
            <package-days-block day="day"></package-days-block>
        </div>
    </div>
    
    <div class='container-fluid' ng-repeat='service in day.services'>
        <service-block service="service"></service-block>
    </div>