1. 程式人生 > >工作日常--遇到angular報錯‘$digest already in progress’

工作日常--遇到angular報錯‘$digest already in progress’

其實昨晚就遇到了這個問題。測試告訴我,在選擇了某個資料作為篩選條件的時候。明明選擇了某個條件,但是篩選失效。

我開啟chrome瀏覽器,打斷點檢視是不是在選擇了該條資料無法觸發請求資料的方法正常執行。後來我發現,選擇了條件是正常的。方法呼叫也是正常的,介面返回資料也是正常的。在一個search介面中新增一個卡ID的篩選條件之後,事實上篩選出來了只有6條資料。可是很明顯,頁面上的資料並不只有6條。一頁20條資料,現在頁面上的資料有上十頁的分頁。由於之前已經打斷點檢視過介面呼叫是成功的,那麼唯一的一個就是angular本身的bug,導致資料無法更新。

結果在自己排查了N遍之後,去查看了控制檯。於是乎就丟擲了異常。點選該異常就在angular官網看到這個

$digest already in progress

以我拙略的英文水平可以理解到這句話的意思是$digest方法已經在執行。其實我是看了csdn一位後端大神寫的解釋angular實現雙向資料繫結原理之後才恍然大悟。這個錯誤的真正意思。我先說我的解決方案吧,既然提出這個報錯。那麼不難發現,是已經在執行$digest方法的時候又一次執行該方法,才會丟擲該異常。故我將第二次的呼叫終止了,完美解決。

其實官網有解釋,我自己雖然看得懂英文。但是需要好久去一個個理解單詞。於是乎我就繼續百度。百度到了’$apply()以及$digest()

看到了以為大神寫的部落格講angular的這兩個方法。其實angular實現雙向資料繫結的原理是這樣子的,使用它的時候需要講資料繫結到scope物件上。然後angular會給scope物件上的所有屬性新增一個watcher,這個watcher跟angular中的$watch方法一樣。當它發現你的試圖中有資料發生變化,那麼在控制器中就會立馬更新相關資料,同時反過來毅然。當你在控制器中更新scope中的屬性物件的時候,也會實時的更新到view中。

等等,angular不是神。他是怎麼知道控制器或者檢視中資料發生了變化的呢?這時候就要提到digest調watcherangular調scope.apply(),調調rootScope.digest()apply()方法有兩種形式。第一種會接受一個function作為引數,執行該function並且觸發一輪digestdigest迴圈。我們馬上會看到為什麼第一種形式更好。

其實angular只能支援在上下文中的任何位置更新model上的資料自動呼叫a

pplymodel調apply。如下的例子

setTimeout(function(){
 $scope.name = 'fred';
 console.log($scope.name);
},2000)

上面的例子中,在兩秒中之後會自動打印出fred。但是在頁面中繫結的name變數並不會實時更新。這時候你就需要手動呼叫該方法才能實現頁面資料更新。程式碼如下

setTimeout(function(){
 $scope.name = 'fred';
 console.log($scope.name);
 $scope.$apply(); // 這樣會觸發$digest實行新一輪的watcher然後頁面資料更新
},2000)

note:以上其實可以直接呼叫timeout調scope.$apply()
到此angular雙向資料繫結的原理基本我瞭解了。

那麼我遇到的問題說明了什麼呢?我在一個非同步中更新資料,在第一個$apply()方法未執行完成,又去非同步呼叫了該方法。導致angular丟擲異常。