2014-09-28 108 views
1

下面的代码:根据Chrome的任务管理器如何解决此Javascript内存泄漏

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对象堆积如山。
  • 对setTimeout的递归调用将旧函数调用保留在内存中。

没有我试过似乎有所作为。

+0

很确定'delete device_div.removeChild(...)'中的* delete *操作符没有做任何事,因为表达式返回的值不是引用类型(所以它只是返回true)。 – RobG 2014-09-28 22:57:39

+0

removeChild在被删除的节点上返回一个引用,而不是布尔型https://developer.mozilla.org/en-US/docs/Web/API/Node.removeChild – 2014-09-28 23:02:17

+0

@PascalLeMerrer-引用和[*类型*参考](http://ecma-international.org/ecma-262/5.1/#sec-8.7)。 – RobG 2014-09-28 23:09:20

回答

0

一旦调用事件侦听器,您应该立即删除事件侦听器。

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

忘记取消注册事件侦听器是内存泄漏的一个非常常见的原因。

+0

将* imageLoaded *的声明移至* refreshContent *之外也应该删除一个循环引用的源。 – RobG 2014-09-28 23:13:11

0

我只是回顾一下我在这里看到的。分别5秒期间:

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

我可能是错的,但在我看来,他们会紧紧地握住一个对方,并且他们可能不会t被垃圾收集。

所以,只要添加一行

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 an image object重复,但它可能是帕斯卡乐Merrer在他的回答一点。