使用ajax加载html内容。浏览器不释放内存

发布于 2024-12-02 04:30:18 字数 3368 浏览 2 评论 0原文

我们有一个单页应用程序,它通过 ajax 调用不同的 Web 服务加载所有内容。起始页面仅加载一次,然后根据用户操作,使用我们在服务器上预渲染的 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 过高,但这里的情况并非如此。

感谢对问题的任何帮助或新观点。谢谢。

We have a single page application which loads all content through ajax calls to different web services. The start page is loaded only once and then depending on the user actions different containers are updated with html packages we prerender on the server.

Now we have a problem that we spotted when the application is running for long periods without restarting. The browser and computer started to get slow and less responsive.
When you look at the process in task manager you can se that it consumes a lot of memory for being a browser process. And the process is not releasing the memory.

I started to investigate the problem and when setting up an example application I found an effect I am wondering about.
The application is simple and consists of a web service method, an aspx page and a javascript file.

Here is the code.

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

Today all our calls to the web service is done with asp.net scriptmanager ajax framework. But if you run this test application you can see some different behaviour between fetching data with jQuery ajax and asp.net ajax, at least in IE9. Chrome seems to be equal but in IE9, when you fetch data with jQuery it does not consumes that lot of memory but in the other case with asp.net ajax it grows and never releases the memory.

I have several question here. First, what is the difference? Are there perfomance losses when using asp.net ajax? And second is there a memory leak in my javascript code? This is usually the pattern we use throughout the application in a simplified example. If there is something wrong we need to know that and correct that.
Is this memory consumption a likely reason to the problem? I have a lot of memory in my developer computer so the browser maybe never releasing the memory because it doesn't have to? Maybe this is false alarm and the problem is something else.
The usual reason when a browser seems unresponsive is the CPU going high but this is not the case here.

Appreciate any help or new viewpoint on the problem. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

安静 2024-12-09 04:30:18

我想我终于找到了这个问题的答案。

IE9 不支持 javascript 函数 eval() : http://support.microsoft.com/kb/2572253< /a>

他们推荐了一些解决方法,其中之一是在处理 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 中遇到同样内存问题的人。

I think I finally have found the answer to this question.

IE9 doesn't support javascript function eval() : http://support.microsoft.com/kb/2572253

They recommend some workarounds, one of them is to use JSON.parse instead when dealing with json deserialization.

We use Ajax Control Toolkit Scriptmanager in our aspx page.
But if you investigate what it does in its internal automatically generated js code you can see this code block:

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

I believe this is the cause of the problem and my option will be to use jquery $.ajax instead.

I hope this will help others who experience the same memory problem in IE9.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文