【发布时间】:2014-01-06 10:14:56
【问题描述】:
我有一个用 AngularJS 编写的 webapp,它基本上轮询一个 API 到两个端点。因此,它每分钟都会轮询以查看是否有任何新内容。
我发现它有一个小的内存泄漏,我已尽力找到它,但我无法做到。在此过程中,我设法减少了我的应用程序的内存使用量,这很棒。
不做任何其他事情,每次民意调查您都会看到内存使用量出现峰值(这是正常的),然后它应该会下降,但它总是在增加。我已经将数组的清理从[] 更改为array.length = 0,我认为我确信引用不会持续存在,所以它不应该保留任何这些。
我也试过这个:https://github.com/angular/angular.js/issues/1522
但没有任何运气......
所以,这是两个堆之间的比较:
大部分泄漏似乎来自 (array),如果我打开,它是 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 - 添加 Promise 展示:
这是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 - 在图像中打开(数组)树
都是这样,所以它是非常没用的恕我直言:(
另外,这里有 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 new heaps。
【问题讨论】:
-
我的赌注是 Promise 挂在你的 then() 回调上。你已经追踪到 Promise 了吗?
-
谢谢@EzekielVictor - 我已经更新了我的答案。我也是这么想的,但老实说,在那之后我认为它不存在了!
-
你能展示其中一个应该被 GC 处理的数组的保留树吗?
-
完成@PieterHerroelen 我还添加了堆报告
-
@AntonioLaguna 无论如何你可以在 plunker/fiddle 中重现这个?
标签: angularjs memory-leaks angularjs-ng-repeat