简体   繁体   English

如何解决此Javascript内存泄漏

[英]How do I fix this Javascript Memory Leak

Here's the code: 这是代码:

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

Memory usage according to Chrome task manager quickly grows when this is running and doesn't when I disable it, so I know it's this portion of the code that's leaking. 根据Chrome任务管理器的运行情况,内存使用量会迅速增加,而禁用它时却不会增加,因此我知道这是泄漏的这部分代码。

Some ideas I have: 我有一些想法:

  • I'm not properly getting rid of all references to the old image, so orphaned Image objects are piling up. 我没有完全摆脱对旧图像的所有引用,因此孤立的Image对象不断堆积。
  • The recursive call to setTimeout is keeping old function calls in memory. 对setTimeout的递归调用将旧的函数调用保留在内存中。

Nothing I've tried seems to make a difference. 我尝试过的一切似乎都无济于事。

You should remove the event listener as soon as it is invoked. 您应该在调用事件侦听器后立即将其删除。

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

Forgetting to unregister an event listener is a very common cause of memory leak. 忘记注销事件监听器是内存泄漏的一个很常见的原因。

I'll just recap what I see here. 我将回顾一下我在这里看到的内容。 Each 5 seconds: 每5秒:

  1. A new id parameter is provided 提供了一个新的id参数
  2. A new function instance (named imageLoaded ) is created, bound to the value of id 创建一个新的函数实例(名为imageLoaded ),绑定到id的值
  3. A new Image is created 创建一个新图像
  4. Image is bound to the imageLoaded function instance 图像绑定到imageLoaded函数实例

I may be wrong, but it seems to me that they will hold one to each other tightly, and that they might not be garbage collected. 我可能错了,但是在我看来,它们将彼此紧紧地抱在一起,而且可能不会被垃圾回收。

So, just adding a line 因此,只需添加一行

image = null;

after

image.addEventListener("load", imageLoaded);

might solve the situation. 可能会解决这种情况。 So, you should end up with: 因此,您应该最终得到:

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;
}

Actually, this is a duplicate of Dispose an image object , but it might be that Pascal Le Merrer has a point in his answer. 实际上,这是Dispose一个图像对象的重复,但是可能Pascal Le Merrer的回答有道理。

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

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