当前位置: 首页 > 面试题库 >

涉及jQuery Ajax请求的内存泄漏

西门庆
2023-03-14
问题内容

我有一个网页正在IE8和Firefox中泄漏内存;Windows Process Explorer中显示的内存使用量只是随着时间的推移而不断增长。

下面的页面请求“ unplanned.json” URL,它是一个永不改变的静态文件(尽管我确实将Cache-controlHTTP标头设置no- cache为确保Ajax请求始终通过)。当得到结果时,它将清除HTML表,遍历从服务器返回的json数组,并为数组中的每个条目动态地向HTML表添加一行。然后等待2秒,然后重复此过程。

这是整个网页:

<html> <head>
    <title>Test Page</title>
    <script type="text/javascript"
     src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
</head> <body>
<script type="text/javascript">
    function kickoff() {
        $.getJSON("unplanned.json", resetTable);
    }
    function resetTable(rows) {
        $("#content tbody").empty();
        for(var i=0; i<rows.length; i++) {
            $("<tr>"
                + "<td>" + rows[i].mpe_name + "</td>"
                + "<td>" + rows[i].bin + "</td>"
                + "<td>" + rows[i].request_time + "</td>"
                + "<td>" + rows[i].filtered_delta + "</td>"
                + "<td>" + rows[i].failed_delta + "</td>"
            + "</tr>").appendTo("#content tbody");
        }
        setTimeout(kickoff, 2000);
    }
    $(kickoff);
</script>
<table id="content" border="1" style="width:100% ; text-align:center">
<thead><tr>
    <th>MPE</th> <th>Bin</th> <th>When</th> <th>Filtered</th> <th>Failed</th>
</tr></thead>
<tbody></tbody>
</table>
</body> </html>

如果有帮助,这是我发回的json的示例(这是一个精确的数组,包含数千个条目,而不只是一个条目):

[
    {
        mpe_name: "DBOSS-995",
        request_time: "09/18/2009 11:51:06",
        bin: 4,
        filtered_delta: 1,
        failed_delta: 1
    }
]

编辑:我已经接受了Toran的非常有帮助的答案,但是我觉得我应该发布一些其他代码,因为他的removefromdomjQuery插件有一些限制:

  • 它仅删除单个元素。因此,您不能给它一个像$(“#content tbody tr”)这样的查询,并且不能期望它删除您指定的所有元素。
  • 您删除的所有元素都必须具有id属性。因此,如果我想删除我的tbody,那么我必须将id分配给我的tbody标签,否则它将给出一个错误。
  • 它会删除元素本身及其所有后代,因此,如果您只想清空该元素,则必须在之后重新创建它(或将插件修改为空而不是删除)。

因此,这是我上面修改过的页面,以使用Toran的插件。为简单起见,我没有采用Peter提供的任何一般性能建议。这是现在不再内存泄漏的页面:

<html>
<head>
    <title>Test Page</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
<!--
    $.fn.removefromdom = function(s) {
        if (!this) return;

        var el = document.getElementById(this.attr("id"));

        if (!el) return;

        var bin = document.getElementById("IELeakGarbageBin");

        //before deleting el, recursively delete all of its children.
        while (el.childNodes.length > 0) {
            if (!bin) {
                bin = document.createElement("DIV");
                bin.id = "IELeakGarbageBin";
                document.body.appendChild(bin);
            }

            bin.appendChild(el.childNodes[el.childNodes.length - 1]);
            bin.innerHTML = "";
        }

        el.parentNode.removeChild(el);

        if (!bin) {
            bin = document.createElement("DIV");
            bin.id = "IELeakGarbageBin";
            document.body.appendChild(bin);
        }

        bin.appendChild(el);
        bin.innerHTML = "";
    };

    var resets = 0;
    function kickoff() {
        $.getJSON("unplanned.json", resetTable);
    }
    function resetTable(rows) {
        $("#content tbody").removefromdom();
        $("#content").append('<tbody id="id_field_required"></tbody>');
        for(var i=0; i<rows.length; i++) {
            $("#content tbody").append("<tr><td>" + rows[i].mpe_name + "</td>"
                + "<td>" + rows[i].bin + "</td>"
                + "<td>" + rows[i].request_time + "</td>"
                + "<td>" + rows[i].filtered_delta + "</td>"
                + "<td>" + rows[i].failed_delta + "</td></tr>");
        }
        resets++;
        $("#message").html("Content set this many times: " + resets);
        setTimeout(kickoff, 2000);
    }
    $(kickoff);
// -->
</script>
<div id="message" style="color:red"></div>
<table id="content" border="1" style="width:100% ; text-align:center">
<thead><tr>
    <th>MPE</th>
    <th>Bin</th>
    <th>When</th>
    <th>Filtered</th>
    <th>Failed</th>
</tr></thead>
<tbody id="id_field_required"></tbody>
</table>
</body>
</html>

进一步编辑:我将保持我的问题不变,尽管值得注意的是,此内存泄漏与Ajax无关。实际上,以下代码将发生相同的内存泄漏,并且可以使用Toran的removefromdomjQuery插件轻松解决:

function resetTable() {
    $("#content tbody").empty();
    for(var i=0; i<1000; i++) {
        $("#content tbody").append("<tr><td>" + "DBOSS-095" + "</td>"
            + "<td>" + 4 + "</td>"
            + "<td>" + "09/18/2009 11:51:06" + "</td>"
            + "<td>" + 1 + "</td>"
            + "<td>" + 1 + "</td></tr>");
    }
    setTimeout(resetTable, 2000);
}
$(resetTable);

问题答案:

我不确定为什么firefox对此不满意,但是我可以从经验中说,在IE6 / 7/8中,您必须设置innerHTML =“”;
要从DOM中删除的对象上。(如果您是动态创建此DOM元素的,则是)

$("#content tbody").empty(); 可能不会释放这些动态生成的DOM元素。

而是尝试如下所示的方法(这是我为解决该问题而编写的jQuery插件)。

jQuery.fn.removefromdom = function(s) {
    if (!this) return;

    var bin = $("#IELeakGarbageBin");

    if (!bin.get(0)) {
        bin = $("<div id='IELeakGarbageBin'></div>");
        $("body").append(bin);
    }

    $(this).children().each(
            function() {
                bin.append(this);
                document.getElementById("IELeakGarbageBin").innerHTML = "";
            }
    );

    this.remove();

    bin.append(this);
    document.getElementById("IELeakGarbageBin").innerHTML = "";
};

您可以这样称呼: $("#content").removefromdom();

唯一的问题是,每次要构建表时都需要重新创建表。

另外,如果这确实解决了IE中的问题,则可以在我今年初遇到相同问题时写的博客文章中了解有关此问题的更多信息。

编辑
我现在将上面的插件更新为95%的JavaScript免费,因此它比以前的版本使用更多的jQuery。您仍然会注意到我必须使用innerHTML,因为jQuery函数html(“”);
对于IE6 / 7/8的作用不同



 类似资料:
  • 问题内容: 我有一个使用安全性约束来锁定对资源访问的Java Web应用程序。当Ajax请求需要身份验证时,我试图操纵HTTP 401响应,因此我创建了一个过滤器,该过滤器观察响应中的HTTP状态,并在需要时进行相应的修改。 问题是,如果需要身份验证,则直到将401发送到浏览器后,过滤器才会被调用。安全约束似乎在请求处理链中的过滤器之前。我的过滤器的url模式比任何安全约束都更通用。平台是WebS

  • 本文向大家介绍讲一下volatile涉及的Java内存模型?相关面试题,主要包含被问及讲一下volatile涉及的Java内存模型?时的应答技巧和注意事项,需要的朋友参考一下 在 JDK1.2 之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的。而在当前的 Java 内存模型下,线程可以把变量保存本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可

  • 我想向一个包含参与者的服务器发出一个异步请求。假设我有两个演员: 和 我的问题是: 1) getSessionIdFromServer()向服务器发出同步请求。我认为异步请求会好得多,对吗?所以它将返回Future[String]而不是一个普通的字符串。 2)我如何使异步:通过使用AsyncHttpClient(如果我没记错的话)或将其同步体包装到Future { } 中? 3)我应该使用阻塞{}

  • 本文向大家介绍请你说一说C++内存溢出和内存泄漏相关面试题,主要包含被问及请你说一说C++内存溢出和内存泄漏时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 1、内存溢出 指程序申请内存时,没有足够的内存供申请者使用。内存溢出就是你要的内存空间超过了系统实际分配给你的空间,此时系统相当于没法满足你的需求,就会报内存溢出的错误 内存溢出原因: 内存中加载的数据量过于庞大,如一次从数据库取出过多

  • 问题内容: 我认为我的android应用正在泄漏内存。我不是绝对确定这是问题所在。 应用程序打开时经常崩溃,并且logcat尝试加载位图图像时会显示“内存不足”异常。 崩溃后,我重新打开了该应用程序,它运行正常。Logcat会显示许多“ gc”,并且JIT表会不时地向上调整大小,而不会向下调整,直到应用程序因内存不足错误而崩溃。 这听起来像是内存泄漏吗?如果是这样,我该如何定位和关闭泄漏点。 这是

  • 问题内容: 我一直在追寻内存泄漏(由“ valgrind –leak-check = yes”报告),它似乎来自ALSA。这段代码已经存在于自由世界中一段时间​​了,所以我猜这是我做错的事情。 输出看起来像这样: 并继续一些页面 这是由于我在一个项目中使用ALSA并开始看到这种巨大的泄漏……或者至少是所说泄漏的报告。 所以问题是:是我,ALSA或valgrind在这里遇到问题吗? 问题答案: ht