2011-08-31 108 views
3

我們有一個單頁應用程序,它通過ajax調用將所有內容加載到不同的Web服務。起始頁面只加載一次,然後根據用戶操作,不同的容器用我們在服務器上預渲染的html包進行更新。使用ajax加載html內容。瀏覽器不釋放內存

現在我們遇到了一個問題,我們發現應用程序長時間運行時未重新啓動。瀏覽器和電腦開始變慢,響應速度變慢。 當您查看任務管理器中的進程時,您可以確定它在瀏覽器進程中消耗大量內存。而這個過程並沒有釋放內存。

我開始研究這個問題,並且在設置示例應用程序時,我發現了一個我想知道的效果。 該應用程序很簡單,包含一個Web服務方法,一個aspx頁面和一個javascript文件。

這是代碼。

的Webservice:

public class WebService1 : WebService 
{ 

    [WebMethod] 
    public string GetData() 
    { 
     var returnValue = ""; 

     var webRequest = WebRequest.Create("http://www.w3schools.com/"); 
     var webResponse = webRequest.GetResponse(); 
     var responseStream = webResponse.GetResponseStream(); 
     if (responseStream != null) 
     { 
      using(var streamReader = new StreamReader(responseStream)) 
      { 
       returnValue = streamReader.ReadToEnd(); 
       var startBody = returnValue.IndexOf("<body>") + "<body>".Length; 
       var endBody = returnValue.IndexOf("</body>"); 
       returnValue = returnValue.Substring(startBody, endBody - startBody); 
      } 
     } 
     return returnValue; 
    } 
} 

.aspx的:

<head runat="server"> 
<title></title> 
<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script> 
<script src="Scripts/JScript1.js" type="text/javascript"></script> 
</head> 
<body> 
<form id="form1" runat="server"> 
<asp:ScriptManager ID="ScriptManager1" runat="server"> 
    <Services> 
     <asp:ServiceReference Path="WebService1.asmx"/> 
    </Services> 
</asp:ScriptManager> 
<input type="button" id="getDataJquery" value="Get data with jQuery"/> 
<input type="button" id="getDataAspnet" value="Get data with asp.net"/> 
<div id="container"></div> 
</form> 
</body> 

的Javascript:

$(document).ready(function() { 

$('#getDataJquery').click(function() { 
    getDataWithJQuery(); 
    setTimeout(function() { 
     $('#container').html(''); 
     $('#getDataJquery').trigger('click'); 
    }, 2000); 
}); 

$('#getDataAspnet').click(function() { 
    getDataWithAspnet(); 
    setTimeout(function() { 
     $('#container').html(''); 
     $('#getDataAspnet').trigger('click'); 
    }, 2000); 
}); 

}); 

function getDataWithJQuery() { 
    $.ajax({ 
     url: 'WebService1.asmx/GetData', 
     type: 'POST', 
     dataType: 'json', 
     success: jQueryResponse, 
     contentType: 'application/json' 
    } 
); 
} 

function getDataWithAspnet() { 
    AjaxJqueryVsAspNet.WebService1.GetData(aspnetResponse); 
} 

function jQueryResponse(response) { 
    loadHtml(response.d); 
} 

function aspnetResponse(response) { 
    loadHtml(response); 
} 

function loadHtml(html) { 
    $('#container').html(html); 
} 

今天我們所有的Web服務調用與asp.net的ScriptManager ajax框架來完成。但是如果你運行這個測試應用程序,你可以看到在jQuery ajax和asp.net ajax之間獲取數據的不同行爲,至少在IE9中。 Chrome似乎是平等的,但在IE9中,當你使用jQuery獲取數據時,它不會消耗大量的內存,但在另一種情況下,它隨着asp.net ajax的增長而不會釋放內存。

我在這裏有幾個問題。首先,有什麼區別?使用asp.net ajax時會有性能損失嗎?第二是我的JavaScript代碼中有內存泄漏嗎?這通常是我們在整個應用程序中使用的簡化示例中使用的模式。如果有什麼問題,我們需要知道並糾正這一點。 這種內存消耗是否可能是問題的原因?我的開發人員計算機中有很多內存,所以瀏覽器可能永遠不會釋放內存,因爲它不必?也許這是虛驚一場,問題是別的。 當瀏覽器看起來沒有響應時,通常的原因是CPU變高,但這不是這種情況。

欣賞對問題的任何幫助或新觀點。謝謝。

+0

有你在不同的瀏覽器進行測試呢?你是否看到其中許多內存使用增加?如果你能縮小它一個瀏覽器,那麼它可能是一個瀏覽器內存泄漏,而不是什麼與您的應用程序。 – Spycho

+0

作爲一個方面說明:您可能希望使用的setInterval,而不是setTimeout的,因爲你似乎想從你的服務器數據重複每2秒。此外,你可能想使您的用戶不會在請求和響應之間的空內容呈現給移動內容清除碼的Ajax響應處理程序。最後,你需要小心點擊處理程序中的超時代碼。如果用戶點擊在T 0毫秒,然後在T 50ms的再次點擊,你會得到通過您的setTimeout在t 2000毫秒內容裝載,並再次在T 2050ms。您可能想要清除超時。 – Spycho

+0

這只是一個測試應用程序。我的意思是「這通常是我們在整個應用程序中使用的模式」是我們稱之爲web服務的方式。測試應用程序中的目的僅在於單擊其中一個按鈕來創建循環。我也清除HTML的容器,看看事情正在發生。我們不會在我們的應用程序中這樣做。是的,問題出現在谷歌瀏覽器和IE9中。 – John

回答

2

我想我終於找到了這個問題的答案。

IE9不支持javascript函數eval():http://support.microsoft.com/kb/2572253

他們推薦一些解決方法,其中之一是使用JSON反序列化處理時使用JSON.parse來代替。

我們在我們的aspx頁面中使用了Ajax Control Toolkit Scriptmanager。 但如果你調查什麼它在其內部自動生成的JS代碼,你可以看到這個代碼塊:

Sys.Serialization.JavaScriptSerializer.deserialize = function Sys$Serialization$JavaScriptSerializer$deserialize(data, secure) { 
    /// <summary locid="M:J#Sys.Serialization.JavaScriptSerializer.deserialize" /> 
    /// <param name="data" type="String"></param> 
    /// <param name="secure" type="Boolean" optional="true"></param> 
    /// <returns></returns> 
    var e = Function._validateParams(arguments, [ 
     {name: "data", type: String}, 
     {name: "secure", type: Boolean, optional: true} 
    ]); 
    if (e) throw e; 

    if (data.length === 0) throw Error.argument('data', Sys.Res.cannotDeserializeEmptyString); 
    try {  
     var exp = data.replace(Sys.Serialization.JavaScriptSerializer._dateRegEx, "$1new Date($2)"); 

     if (secure && Sys.Serialization.JavaScriptSerializer._jsonRegEx.test(
      exp.replace(Sys.Serialization.JavaScriptSerializer._jsonStringRegEx, ''))) throw null; 
     return eval('(' + exp + ')'); 
    } 
    catch (e) { 
     throw Error.argument('data', Sys.Res.cannotDeserializeInvalidJson); 
    } 
} 

我相信這是問題的原因,我的選擇將是使用jquery $就代替。

我希望這將幫助其他人誰在IE9中遇到同樣的內存問題。