2016-02-25 27 views
8

我有一个AngularJS 1.4 *应用程序在本地运行(还)。此应用程序由Laravel 5.1后端RESTFul API提供。为什么我的观察者在相同的变化中被调用两次?

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

我的网络服务器(我的laravel应用程序从中使用该服务器)为我提供了一个预先设置的包,其中包含一个天数列表:每个包含一个服务列表和一个酒店数据(到目前为止尚未使用)。在响应中,我有一个包的属性列表(目前无关紧要)和一系列天数,称为days_info。该回复正在放入$scope.package,我的PackageControllerPackageController还声明了一个名为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> 

这就是问题开始的地方:我undestandment,我现在有一个$scope.serviceServiceController内。所以,我开始通过$scope.serviceServiceController之内改变它。

$ scope.service有一个属性,名为service_id。我在上面放了一个监听器/监听器,所以在任何时候改变了$ scope.service.service_id,我都要求另一个service_table(保存有关服务的信息,它基于之前由用户选择或更改的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; 
     }, 
     ... 
    ); 

reloadServicesTable被称为在观察者的的service_id变化。

// 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阵列运行,并读取service.table内的属性price的价值另一部分:service.table.price。在那里,我意识到有两个范围的:我处理的和另一个我没有创意想法它来自哪里!

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

任何想法为什么会发生这种情况?

PS:这是我的第一个AngularJS应用程序,因此,采取容易,如果我搞砸了的东西基本...

编辑:

由于在评论中指出由一个老乡,我问题不是很重复。可悲的是,我不能只把我怀疑的部分放在这里,因为我没有丝毫的想法问题在哪里! (我知道这是没有太大的帮助)

我把从Chrome控制台一些屏幕截图:

首先,requestions发射了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上的观察者?

的呼吁资金价格从differente地叫了两声,因为你可以在下面的图片中看到:

Call Stack for the sumPrices method on PackageController

+3

你的问题太长,而且含有大量的不相关的信息,但是缺少一个可重复的测试案例。所以很难理解问题究竟是什么。但文档说:* [...]在极少数情况下,这是不可取的,因为当watchExpression的结果没有改变时调用监听器。要在侦听器fn中检测到这种情况,可以比较newVal和oldVal。如果这两个值相同(===),则由于初始化而调用侦听器。 –

+5

通常,使用手表是一个坏主意。如果你以简单的方式告诉我们你想达到的目标,我们可以帮助你找到更好的方法。 –

+0

我正在比较比较函数后调用的fn中的两个值(newValue和oldValue)。这似乎不是问题(再)。由于函数被系统地调用了两次!我将从我的请求网络日志中放置两个打印文件,并在请求更改服务时使用一个范围。 –

回答

3

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

  1. 的原因对我来说,控制器渐渐重新初始化,并且有一个单独的API调用写的,其目的是最初加载页面。

  2. 还有一种情况是您在标记中分配了两次控制器。

+0

这确实是发生在我身上的事!你没有得到14秒的赏金。 = /已经分配给罗伯特。我为div编写了一个'ng-controller',并在同一个控制器上调用了一个指令,因此实例化了它两次!这是问题。 –

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 ng-repeat控制器没有什么意义。 <service-block><package-days-block>是处理逻辑的E指令。

只写一个你PackageController观察家认为观看package.days_info当你dayservice变化,它可以简单地找出并做一些事情。

只需冷静并修复它。

+0

问题不完全是这样。但是,提示很好!非常好。既然我可能会从现在开始使用它,我会给你赏金(并在22分钟内过期)。非常感谢。 –

相关问题