繁体   English   中英

如何解决此Javascript内存泄漏

[英]How do I fix this Javascript Memory Leak

这是代码:

function refreshContent(id) {
    function imageLoaded(){
        //get device div
        var device_div = document.getElementById("device-" + id);

            //remove old image, if there is one
        if(device_div.hasChildNodes()) 
            delete device_div.removeChild(device_div.lastChild);

        device_div.appendChild(image);
        var device_id = device_div.id.split("-")[1]; //divs are named "device-<something>"
        window.setTimeout(refreshContent, 5000, device_id);
    }
    var image = new Image();
    image.src = SERVER_BASE_URL + "/api/test/" + id + "/image/" + new Date().getTime();


    image.addEventListener("load", imageLoaded);
}

根据Chrome任务管理器的运行情况,内存使用量会迅速增加,而禁用它时却不会增加,因此我知道这是泄漏的这部分代码。

我有一些想法:

  • 我没有完全摆脱对旧图像的所有引用,因此孤立的Image对象不断堆积。
  • 对setTimeout的递归调用将旧的函数调用保留在内存中。

我尝试过的一切似乎都无济于事。

您应该在调用事件侦听器后立即将其删除。

function refreshContent(id) {
    function imageLoaded(){

        image.removeEventListener("load", imageLoaded);

        //get device div
        var device_div = document.getElementById("device-" + id);

            //remove old image, if there is one
        if(device_div.hasChildNodes()) 
            delete device_div.removeChild(device_div.lastChild);

        device_div.appendChild(image);
        var device_id = device_div.id.split("-")[1]; //divs are named "device-<something>"
        window.setTimeout(refreshContent, 5000, device_id);
    }
    var image = new Image();
    image.src = SERVER_BASE_URL + "/api/test/" + id + "/image/" + new Date().getTime();


    image.addEventListener("load", imageLoaded);
}

忘记注销事件监听器是内存泄漏的一个很常见的原因。

我将回顾一下我在这里看到的内容。 每5秒:

  1. 提供了一个新的id参数
  2. 创建一个新的函数实例(名为imageLoaded ),绑定到id的值
  3. 创建一个新图像
  4. 图像绑定到imageLoaded函数实例

我可能错了,但是在我看来,它们将彼此紧紧地抱在一起,而且可能不会被垃圾回收。

因此,只需添加一行

image = null;

image.addEventListener("load", imageLoaded);

可能会解决这种情况。 因此,您应该最终得到:

function refreshContent(id) {
  function imageLoaded() {
    //get device div
    var device_div = document.getElementById("device-" + id);

    //remove old image, if there is one
    if (device_div.hasChildNodes())
      delete device_div.removeChild(device_div.lastChild);

    device_div.appendChild(image);
    var device_id = device_div.id.split("-")[1]; //divs are named "device-<something>"
    window.setTimeout(refreshContent, 5000, device_id);
  }
  var image = new Image();
  image.src = SERVER_BASE_URL + "/api/test/" + id + "/image/" + new Date().getTime();


  image.addEventListener("load", imageLoaded);
  image = null;
}

实际上,这是Dispose一个图像对象的重复,但是可能Pascal Le Merrer的回答有道理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM