2016-02-25 78 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分鐘內過期)。非常感謝。 –

相關問題