2014-03-07 70 views
1

在我們的應用程序中,我們有一個相當複雜的模型對象,它通過對後端的多次調用進行初始化。我們已經完成了我們自己的「髒」檢查實現,即我們觀察模型對象的任何變化,只有當我們知道模型對象在初始化初始化之後確實發生了變化時,用戶纔有機會保存它們的變化。

「髒」標記由$watch函數自動引發,該函數監視可能由於用戶操作而更改的模型對象部分。我們還有一個功能,用於在完成初始化後清除標誌(這當然會更改模型的狀態並觸發觀察者),並使用$emit調用實施。

所以,這個想法是請按照下列步驟操作:

  1. 初始化模型多次打電話給後端
  2. 清除「髒」標誌
  3. 手錶更改模型對象,如果發生這種情況,請提高標記

但是,現在我們遇到了一個問題,即在初始化之後,模型似乎立即被修改。如果我正確地追蹤了問題,則會發生這種情況,因爲$emit調用清除標誌是在啓動$watch之前運行的。

什麼是最好的方式來確保在觀察者被調用後標誌被清除?

此外,這個問題已經出現一段時間了,可能與我們升級到AngularJS 1.2有關 - 但這也可能只是一個巧合。

編輯:爲標誌結算通話監聽器使用$evalAsync推遲變化,具體如下:

$scope.$on('resetModelChangeCounter', function(event) { 
    event.targetScope.$evalAsync(function() { 
    ourModel.setUnchanged(); 
    }); 
}); 

編輯#2:這裏的展示行爲的小提琴:http://jsfiddle.net/LVrVj/1/

+1

一個的jsfiddle/Plunker用最少的攝製會有所幫助。 –

+0

當然。現在增加一個,它顯示了問題:在設置標誌之前清除標誌,從而使標誌處於打開狀態。 – MJV

回答

1

查看代碼,您基本上觸發了AngularJS必須處理的兩件事:信號和手錶。

$scope.exampleModel.internalObject.secondKey = "anotherValue"; 
// this is initialization, so we don't want the change to enable saving 
$scope.$emit('resetModelChangeCounter'); 

您是否期待這些事件按照您觸發它們的順序發生?我不會相信這個假設,在這種情況下,摘要循環似乎在信號處理之前觸發手錶。

無論如何,您可以在新的超時中包裹信號,並在摘要週期結束並且手錶已被觸發後處理。

我更新這裏的小提琴: http://jsfiddle.net/LVrVj/2/

+0

真正的代碼實際上是由其他人編寫的,但我得出了同樣的結論 - 並且對信號的反應是'$ evalAsync'來強制執行所需的順序。但它似乎不再適用(可能是由於1.2版Angular中的某些變化)。無論如何,發射端的'$ timeout'似乎可以做到這一點,它也可以在沒有'$ evalAsync'的情況下工作。謝謝! – MJV

+0

由於發出的信號實際上是從幾個地方發送的,所以我將'$ timeout'移到了接收端以避免重複,從而取代了舊的'$ evalAsync':http://jsfiddle.net/LVrVj/3/只是一個小小的調整。 :) – MJV