我们有一个单页应用程序,它通过 ajax 调用不同的 Web 服务来加载所有内容。起始页面仅加载一次,然后根据用户操作,使用我们在服务器上预渲染的 html 包更新不同的容器。
现在,当应用程序长时间运行而不重新启动时,我们发现了一个问题。浏览器和计算机开始变得缓慢且响应速度变慢。 当您在任务管理器中查看该进程时,您可以发现它作为浏览器进程消耗了大量内存。并且该进程没有释放内存。
我开始调查这个问题,在设置示例应用程序时,我发现了我想知道的效果。 该应用程序很简单,由一个 Web 服务方法、一个 aspx 页面和一个 JavaScript 文件组成。
这是代码。
网络服务:
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 过高,但这里的情况并非如此。
感谢对问题的任何帮助或新观点。谢谢。
最佳答案
我想我终于找到了这个问题的答案。
IE9 不支持 javascript 函数 eval() : http://support.microsoft.com/kb/2572253
他们推荐了一些解决方法,其中之一是在处理 json 反序列化时使用 JSON.parse。
我们在 aspx 页面中使用 Ajax 控制工具包 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 $.ajax 代替。
我希望这能帮助其他在 IE9 中遇到同样内存问题的人。
关于jquery - 使用ajax加载html内容。浏览器不释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7256437/