2014-09-28 109 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在他的回答一點。