为什么我的观察者会在同一次更改中被调用两次?

时间:2016-02-25 23:17:53

标签: angularjs angularjs-scope angularjs-ng-repeat

我有一个在本地运行的AngularJS 1.4 *应用程序。此应用程序由Laravel 5.1后端RESTFul API提供。

我必须制作代表旅行套餐的应用程序。包裹由天组成,范围从0到N天。每天都有一系列服务,范围从0到N服务。还有一家酒店。

我的laravel应用程序所使用的Web服务器为我提供了一个预先设置的包,其中包含一个日期列表:每个包含服务列表和酒店数据(目前尚未使用)。在响应中,我有一个包的属性列表(暂时不重要)和一系列日期,称为days_info。该回复放在$scope.packagePackageController 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>

<package-days-block>内部指令中,我有另一个在每天内遍历服务列表。

<div class='container-fluid' ng-repeat='service in day.services' ng-controller="ServiceController">
    <service-block></service-block>
</div>

问题开始的地方:我的不正确,我现在$scope.service内有一个ServiceController。所以,我开始在ServiceController内通过$scope.service来改变我的需求。

$ scope.service 有一个名为service_id的属性。我把一个监听器/观察器放在上面,所以在任何时候 $ scope.service.service_id 都被改变了,我要求另一个service_table(保存有关服务的信息,它&#39} ; s基于之前由用户选择或更改的service_id),并将其放入$scope.service.table

// 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;
        }, 
        ...
    );

观察员会在{strong> service_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);

    }
);

问题从这里开始:当service_id仅更改一次时,将调用服务表的请求两次。

为什么,上帝,为什么?!

我的代码的另一部分,我从 PackageController 运行整个days_info数组,并读取内部属性price的值service.table:service.table.price。在那里,我意识到有两个范围:我处理的那个,另一个我没有 FREAKING IDEA 来自哪里!

如果我在运行 days_info 的方法中放置console.log($scope);,我会为每个请求获得两个范围。此方法位于 PackageController

为什么会发生这种情况?

P.S。:这是我的第一个AngularJS应用程序,所以,如果我搞砸了一些基本的东西,请放轻松......

修改

正如一位评论员所指出的那样,我的问题不是很可重复。可悲的是,我不能只把我怀疑的部分放在这里,因为我不知道问题在哪里! (我知道这不是很多帮助)

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

首先,对service_id

的更改发出了请求

Request log for the service change (ordered by path name)

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

另一个图像是来自PackageController $ scope的 console.log 的输出,在service_id被更改时。

Scopes for the PackageController

如您所见,有两个不同的范围。 b范围是r范围的儿子。 r范围也在调用service_id上的观察者?

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

Call Stack for the sumPrices method on PackageController

2 个答案:

答案 0 :(得分:3)

它可以解决你的问题。即使我面对的也和你提到的完全一样。

  1. 我的理由是,控制器再次初始化,并且有一个单独的api调用,最初用于加载页面。

  2. 您还可以在标记中为控制器分配两次。

答案 1 :(得分:1)

<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>

dayservice传递给指令。使用双向绑定将dayservice更改传递回package.days_info。

删除你的ServiceController对重复控制器没有多大意义。 <service-block><package-days-block>是处理逻辑的E指令。

只在您的 PackageController 中只编写一位观察者package.days_info当您dayservice更改时,它可以简单地找到并执行某些操作。

Just Chill并解决它。