我有一个使用范围的复杂指令:true.这实际上是我正在努力编写清理代码的ng-grid最新的2.x版本,因为它只是像内存一样泄漏内存,我们的应用程序现在就被“卡住”了.这是the plunk that demos the problem.当您点击网格并检查堆快照之后,您会看到几个“unattached”ngGrid对象.这些仅由指令的范围内的听众阻止.
当我通过点击多个网格(状态)更改状态(使用ui.route最新版本)时,grid指令的范围是获取$destroy事件.处理程序正在工作.但是,范围本身并没有得到$destroy()的调用.我在堆快照中看到,该指令的范围仍然通过$$监听器持有元素.而且,范围.$$销毁没有设置.
但是,scope.prototype IS被破坏.因为它是,我甚至不能调用$scope.$destroy从指令的$on $destroy处理程序,因为proto的$destroy()调用将$destroy的定义更改为noop:
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是一个$timeout(给我的时间指令完成清理在我的$$摧毁监听器似乎工作,但是觉得内部错误,有时它是浏览器完成清理时间不够长,这只是一个解决方案.
我也试过这个:
那么什么是阻止我的指令的范围获得$destroy()自动调用呢?
起初,我以为这是因为我们在指令选项中使用范围:true,因为原始范围似乎已被破坏.所以我写了a plunk to try that theory out.但是用这个plunk,指令的范围被正确地破坏,没有物体被泄漏.非常惊讶,实际上但是我并没有使用同样的视图嵌套我在第一个plunk;不过我怀疑是这样的.当视图发生变化时,控制器范围仍会被擦除.我还有一个内部对象的观察者.所以我想我会看到类似的动态.但是,似乎在该内部范围内真正地调用了$destroy.
关于什么会阻止指令范围获得$destroy()调用的任何想法? IT似乎与范围有关:真的有点,但是我不能相当的思考角度内部的内容,足以说明为什么.
先谢谢你,
杰西
更新:好的,我会发布更新到这个问题.
就我的能力而言,似乎正在发生的是元素的主要范围(不是网格伪指令的半隔离范围)得到$destroy()d.但是,将该范围作为原型使用的子范围很可能会早于$destroy方法,因为self.$$被破坏是真的(原型继承).所以听众和观察者都不清楚.
我可能会更新这个指令是完全孤立的,但是我没有时间来解决这个问题.
我也发现它不仅仅是$摧毁. $scope本身具有大量功能,它由该指令定义,该函数在内部vars上形成闭包,内部vars占用大量内存.
所以,我写了一个服务,提供额外的清理,很容易注入到可疑的网格指令中.我有一个plunk演示,但我不能发布在主要的片段,由于我的声誉很低:).现在,您可以切换所有您喜欢的网格,没有,但目前的网格将保留在堆上.
希望这有助于人们前进,
Ĵ