jQuery Memory Leak Suspicion

时间:2011-12-01 20:56:16

标签: javascript jquery

我正在为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 ();

编辑我已经结合了一些人的想法和一些成功的处理程序内部。我看到增长率较小,但不是很多。

4 个答案:

答案 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);
        }
    });
};
}

这应该只回拨一次。

相关问题