我正在为XML做一个AJAX请求。我这样做每一秒。我注意到我的内存使用量增长到数百兆字节。正如您可能想象的那样,客户对此并不满意。在各个地方做了一些阅读后,我怀疑功能关闭引起了我的头痛。我正在寻找可以获得的任何验证以及如何解决它的任何帮助。
function PageManager () {
var self = this;
self.timeoutHandler = function () {
$.ajax ({
url: 'URLtoXML',
type: 'post',
cache: false,
context: self,
success: function (data) {
var slf = this;
var xmlDoc = $($.parseXML (data));
xmlDoc.find ("tag_label").each (function () {
self.val = parseInt ($.trim ($(this).text ()));
}
setTimeout (slf.timeoutHandler, 750);
}
});
}
}
var pm = new PageManager ();
pm.timeoutHandler ();
编辑我已经结合了一些人的想法和一些成功的处理程序内部。我看到增长率较小,但不是很多。
答案 0 :(得分:6)
为了避免任何新创建的函数(上下文)在此处关闭其父作用域,您只需要删除setTimeout
中的匿名函数。所以
setTimeout(self.timeoutHandler, 750);
然而,即使该闭包会覆盖父上下文,任何一半体面的垃圾收集器(像任何现代浏览器一样)都会注意到它并在方法触发后释放内存。你没有提到的非常重要的事情是你注意到了哪种浏览器的行为。例如,Firefox垃圾收集器工作..非常不可思议(至少对我来说)。它将允许越来越多的内存被使用,然后在某些时候,它将再次释放一大块。
要查看发生了什么,请使用Firefox并在脚本运行时查看about:memory
。
在那里你会看到记忆的去向。如果内存使用量增加一段时间,我不会担心。看看它,如果这是你的所有代码,内存应该迟早被释放。
答案 1 :(得分:0)
当你保持对事物的引用时,内存会增长。当你不小心这样做时,这是一个泄漏。
在这种情况下,你的函数timeoutHandler
会自己调用,而且会再一次......它永远无法清理调用堆栈。我敢打赌这是你的泄密。
要避免此问题,请使用setInterval
。它的工作原理与setTimeout
完全相同,但它会每隔毫秒继续调用该函数,直到用clearTimeout
清除它(或直到世界结束)。
缺点是你不能很好地计时,你的当前实现总是在每次调用后等待750毫秒。我想你可以做一些花哨的东西,它仍然可以让你把它计时(用Date
来检查时间),但这不是我在10秒内写的东西:P
答案 2 :(得分:0)
我只想投入两美分,但我同意jAndy(+1)。但是,我会生成一次绑定回调,而不是在回调的迭代中创建一个新的闭包(理论上可以使范围和xml数据保持活动的时间比你想要的要长很多。我建议另外一个像这个:
function PageManager () {
var callback = (function(self) {
return function() { self.timeoutHandler(); };
})(this); // only one callback
this.timeoutHandler = function () {
$.ajax ({
url: '/echo/json/',
type: 'post',
cache: false,
data: {a:Math.random() },
success: function (data) {
//var xmlDoc = $($.parseXML (data));
// Processing of XML
//alert("data");
setTimeout (callback, 750);
}
});
};
}
var pm = new PageManager ();
pm.timeoutHandler();
修改的
Here is a jsFiddle使用上面的代码,我观察了内存管理一段时间,但在任何意义上都不足以确定内存。
答案 3 :(得分:0)
您的超时功能
setTimeout(self.timeoutHandler, 750);
可能导致内存泄漏。虽然成功:回调能够在完成后退出,但在setTimeout回调中可能没有空的上下文导致循环循环。 你应该取出匿名函数来结束这样的事情:
var pManager = new PageManager ();
pManager.timeoutHandler();
function PageManager () {
var ret = (function(self) {
return function() { self.timeoutHandler(); };
})(this);
this.timeoutHandler = function () {
$.ajax ({
url: '/echo/json/',
type: 'post',
cache: false,
success: function (data) {
setTimeout (ret, 750);
}
});
};
}
这应该只回拨一次。