2014-10-05 69 views
12

在檔案和網絡尋找答案,但沒有真正找到一個,只是點點滴滴。似乎有很多建議的帖子,但沒有一個人有答案。

我有一個複雜的指令,它使用範圍:true。這實際上是我試圖編寫清理代碼的ng-grid最新的2.x版本,因爲它只是像瘋了一樣泄漏內存,我們的應用程序現在已經「卡住」了。這是the plunk that demos the problem。當你點擊網格並在之後檢查堆快照時,你會看到幾個「未連接」的ngGrid對象。這些只是聽衆對指令範圍的限制。

當我通過單擊多個網格(狀態)來更改狀態(使用ui.route latest)時,網格指令的作用域是獲取$ destroy事件。處理程序正在工作。然而,範圍本身並沒有獲得$ destroy()的調用。我在堆快照中看到,指令的作用域仍然通過$$監聽器保存到元素中。此外,範圍。$$銷燬未設置。

但是,範圍。 原型IS已銷燬。而且因爲它是,我甚至不能調用$範圍$從該指令的$導通$銷燬處理程序破壞,因爲原始的$ destroy()方法調用改變$定義破壞到空操作。

ngGridDirectives.directive('ngGrid', ['$compile', '$filter', '$templateCache', '$sortService', '$domUtilityService', '$utilityService', '$timeout', '$parse', '$http', '$q', 
    function($compile, $filter, $templateCache, sortService, domUtilityService, $utils, $timeout, $parse, $http, $q) { 
    var ngGridDirective = { 
    scope: true, 
    compile: function() { 
     return { 
     pre: function($scope, iElement, iAttrs) { 
      $(iElement).on('$destroy', function cleanupElementNgGrid() { 
       $timeout(function() { 
       $scope.$destroy(); 
       $scope.destroyedByForce = true; 
       console.log("I destroyed it."); 
       },4000); 
      }); 
     ... 

設置範圍$$ listeners = {}的超時時間爲2000(爲了讓指令在我的$ destroy消息監聽器中完成清理工作的時間似乎有效,但是與內部消耗有關的感覺是錯誤的,有時它是。沒有足夠長的瀏覽器來完成清理這只是一個變通/雜牌

我也試過這樣:

那麼,什麼是防止我的指令的範圍˚F rom獲取$ destroy()自動調用它?

起初,我認爲這是因爲我們在指令選項中使用scope:true,因爲proto作用域似乎已被破壞。所以我寫了a plunk to try that theory out。但是,隨着這個龐然大物,指令的範圍被正確銷燬,並且沒有物體泄漏。實際上非常令人驚訝。但是我並沒有在第一個階段使用同樣的觀點,然而我懷疑這就是它。控制器範圍在視圖改變時仍然被擦除。我仍然對內部對象有一個觀察者。所以我想我會看到類似的動態。但是看起來,$ destroy真的被稱爲內部範圍。

關於什麼會阻止指令作用域獲取$ destroy()的任何想法? IT似乎與範圍有關:真實的一點,但我不能很滿意地說Angular內部的原因。

謝謝你在前進,

傑西


更新:OK,我會發布的更新這個問題。

盡我所能,似乎發生的事情是元素的主要作用域(不是grid指令的半隔離範圍)得到$ destroy()d。但是,使用該範圍作爲原型的子範圍很可能會很早地從$ destroy方法中解脫出來,因​​爲self。$$銷燬是真實的(原型繼承)。所以聽衆和觀察者不會被清除。

我大概可以更新指令,將其完全隔離在範圍內,但我沒有時間來理清它的含義。

我還發現它不僅僅是$ destroy。 $ scope本身有很多由內部變量形成閉合的指令定義的函數,這些變量持有大量內存。

所以,我寫了一個服務,提供額外的清理,很容易注入可疑的網格指令。我有一個plunk demo'ing它,但由於我的低聲譽,我無法將它發佈在主要部分:)。現在,你可以切換所有你喜歡的網格,但是當前的網格將保持在堆上。

希望這可以幫助別人前進,

Ĵ

+1

下面是顯示上述分辨率的其他plunk的鏈接。 http://plnkr.co/edit/r2uTKTJW2yJTbHx0kXYB – jessewolfe 2014-10-07 03:56:02

+0

嗨,我有一個問題,我認爲是相關的,你有沒有找到$ destroy的原因不被調用的範圍? http://stackoverflow.com/questions/27467210/angular-directive-memory-leaks – Barnash 2014-12-28 15:15:26

+0

也許有趣:這篇文章講述了由於子範圍的糟糕問題(即:使用jquery)在$ destroy鏈中可能發生的中斷http: //www.bennadel.com/blog/2706-always-trigger-the-destroy-event-before-removing-elements-in-angularjs-directives.htm – Offirmo 2015-01-05 17:34:06

回答

1

不知道這是否是更適合作爲註釋與否。我最近在一個使用ng-grid + angularjs的大型項目上工作,我們遇到了所有遇到的問題:內存泄漏。我們發現並不是所有的東西都能很好地清潔,範圍和手錶都漏到了地方。

我們嘗試添加一些自定義邏輯來嘗試做一個更好的清理,但它並沒有解決我們的問題100%。我們的問題在ng-grid上橫向滾動+虛擬化也會加劇,因此記住這一點也許會很有用(如果我沒記錯的話,他們計劃在未來的版本中解決這個問題)。