我有一个用AngularJS编写的Web应用程序,基本上轮询两个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 个新堆。
$broadcast()
之后将response
设置为null
,会发生什么?这种递归不会导致堆栈溢出吗? - Pieter Herroelen