我有一个用AngularJS编写的webapp,它基本上将API轮询到两个端点.所以,它每分钟都会进行一次调查,看看是否有新的东西.
我发现它有一个小的内存泄漏,我已尽力找到它,但我无法做到.在这个过程中,我设法减少了我的应用程序的内存使用量,这很棒.
在没有做任何其他事情的情况下,每次调查你都可以看到内存使用量的增长(这是正常的)然后它应该下降,但它总是在增加.我从改变阵列的清洗[]
到array.length = 0
,我想我敢肯定,引用不持续存在,因此它不应该被保留的任何现象.
我也试过这个:https://github.com/angular/angular.js/issues/1522
但没有运气......
所以,这是两个堆之间的比较:
大多数泄漏似乎来自(数组),如果我打开,它是通过解析API调用返回的数组,但我确定它们没有被存储:
这基本上是结构:
poll: function(service) { var self = this; log('Polling for %s', service); this[service].get().then(function(response) { if (!response) { return; } var interval = response.headers ? (parseInt(response.headers('X-Poll-Interval'), 10) || 60) : 60; services[service].timeout = setTimeout(function(){ $rootScope.$apply(function(){ self.poll(service); }); }, interval * 1000); services[service].lastRead = new Date(); $rootScope.$broadcast('api.'+service, response.data); }); }
基本上,假设我有一个sellings
服务,那就是service
变量的值.
然后,在主视图中:
$scope.$on('api.sellings', function(event, data) { $scope.sellings.length = 0; $scope.sellings = data; });
并且视图确实具有ngRepeat
根据需要呈现的视图.我花了很多时间试图自己解决这个问题,但事实并非如此.我知道这是一个很难的问题但是,有没有人知道如何追踪这个问题?
编辑1 - 添加承诺展示:
这是makeRequest
两个服务使用的功能:
return $http(options).then(function(response) { if (response.data.message) { log('api.error', response.data); } if (response.data.message == 'Server Error') { return $q.reject(); } if (response.data.message == 'Bad credentials' || response.data.message == 'Maximum number of login attempts exceeded') { $rootScope.$broadcast('api.unauthorized'); return $q.reject(); } return response; }, function(response) { if (response.status == 401 || response.status == 403) { $rootScope.$broadcast('api.unauthorized'); } });
如果我注释掉$scope.$on('api.sellings')
部件,泄漏仍然存在,但下降到1%.
PS:我使用最新的Angular版本
编辑2 - 图像中的打开(数组)树
这就是一切,所以它是无用的imho :(
此外,这里有4个堆报告,您可以自己玩:
https://www.dropbox.com/s/ys3fxyewgdanw5c/Heap.zip
编辑3 - 响应@zeroflagL
编辑指令,对泄漏没有任何影响,虽然封闭部分似乎更好,因为它没有显示jQuery缓存的东西?
该指令现在看起来像这样
var destroy = function(){ if (cls){ stopObserving(); cls.destroy(); cls = null; } }; el.on('$destroy', destroy); scope.$on('$destroy', destroy);
对我来说,似乎正在发生的事情就是这一点(array)
.在民意调查之间还有3个新的堆.
答案就是缓存.
我不知道它是什么,但这件事情增长了.它似乎与jQuery有关.也许这是jQuery元素缓存.你是否有机会在每次服务电话后在一个或多个元素上应用jQuery插件?
问题是添加了HTML元素,使用jQuery进行处理(例如通过popbox插件),但是从未删除过或者没有使用jQuery删除.在这种情况下处理意味着添加事件处理程序之类的东西.缓存对象中的条目(无论它是什么)只有在jQuery知道元素已被删除时才会被删除.这就是必须使用jQuery删除元素.
目前尚不清楚为什么缓存中的这些条目没有被删除,因为当它被包含时,angular应该使用jQuery.但它们是通过评论中提到的插件添加的,并包含事件处理程序和数据.AFAIK Antonio更改了插件代码以取消绑定事件处理程序并删除插件destroy()
方法中的数据.这最终消除了内存泄漏.