浏览器通过AJAX + setInterval继续使用内存

时间:2011-04-18 12:25:19

标签: javascript jquery ajax memory-leaks

我需要使用JavaScript更新给定时间间隔内的大量数据。问题是,无论我使用什么JS库(甚至是裸骨js),所有浏览器似乎都在每个AJAX请求上分配内存,并且之后无法释放它。这是一个应该重现错误的示例:

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <title>Memleak Test</title>
            <meta charset="utf-8" />
            <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
            <script type="text/javascript">

                function readData() {
                    $.getJSON('data.php');
                }

                $(document).ready(function() {
                    setInterval(readData, 1000);
                });
            </script>
        </head>
        <body>
            <div id="content"></div>
        </body>
    </html>

jsbin

提供了一个等效的测试页面

以下是有关此内容的更多信息:

  • 我还尝试在setInterval()调用中直接将readData()函数作为闭包。这似乎没有任何区别。
  • 我在这里使用jQuery,但任何其他库都会产生相同的错误。
  • 我的data.php脚本只是在PHP中生成一个带有json_encode()的假JSON-Object。
  • 我知道这里的一秒钟时间很短,在我的制作脚本中,时间范围是30秒。我只是想更快地看到效果(在制作应用程序中需要几个小时,但内存也已满了。)
  • 这里的问题是该应用程序将全天候开放。

看起来很简单,我认为我在这里做了一些非常错误的事情,如果这里的一些JS大师可以帮助我的话会很棒!

7 个答案:

答案 0 :(得分:4)

相同发布的一个可能问题是如果XHR请求花费的时间超过轮询周期(平均而言),则待处理请求的队列将会增加。如果Web服务器本身开始积压请求,则可能会变成恶性循环。

要避免这种情况,请使用CPS样式编码,使用适当的回调完成下一个操作。也就是说,在需要之前不会启动下一个请求(先前的请求完成:成功或失败) - 如果有大量未完成的请求,此方法仍可用于创建具有可控大小的手动请求队列是必需的。

此外,请确保未使用的对象 有资格进行回收,因为这是GC语言中“内存泄漏”的“标准”原因。

快乐的编码。


帖子中的代码不包含任何内在泄漏内存的内容。它可能是jQuery内部的一个问题,但这只是猜测。此外,监控XHR / Web请求的Firebug等工具可以消耗大量内存,因此需要检查并确保该行为不是Heisenberg。


此外,请记住,增加内存使用量并不表示内存泄漏,除非它无限增长。垃圾收集周期只会在主机感觉到它时才会发生。

答案 1 :(得分:3)

只是一个想法,而不是setInterval你应该使用setTimeout然后当它超时你再次设置超时。

这样你就不会冒着setInterval运行的风险,如果你因为某些原因而忘记了它:

我认为jquery ajax还有一个成功的回调函数,可以用作setTimeout的点。这样,就像其他地方的这个帖子中提到的那样,你最终不会重叠请求。

(刚刚检查并且成功回调)

答案 2 :(得分:0)

答案 3 :(得分:0)

答案 4 :(得分:0)

由于您在每个请求上加载了更多数据,因此会增加内存使用量。

Clicky:

How to free memory after an Ajax request

Memory leak involving jQuery Ajax requests

答案 5 :(得分:0)

根据this jQuery forum thread

...
success: function(data) {

    // the line below prevents the leak, apparently
    document.getElementById("theContainer").innerHTML = ""; 
    $("#theContainer").html(data);
}

答案 6 :(得分:0)

您是否尝试重用调用中的变量?意味着不是在处理响应的地方创建新变量,而是使用相同的变量。说

window.myvar = response["myvar"];

这真的是一个泄漏,这可能有助于垃圾收集器。看到你正在做的事情的实际代码会很高兴。