【问题标题】:Memory leak with jquery dialog e jqgrid内存泄漏与 jquery 对话框 e jqgrid
【发布时间】:2014-02-24 14:05:24
【问题描述】:

我有以下创建一个 jQuery 对话框并在其上设置一个 jqGrid 的函数。 我的代码在 IE 8 中运行。

每次打开对话框时,我都会注意到浏览器的内存增加了大约 30 MB。 当我关闭对话框时,该内存不会被释放。

这段代码在哪里泄露?

function ShowData() {
    var gridID = "my_detail_grid";
    var pagerID = gridID + "_pager";
    var markup = $('<div style="display: none;">' +
                    '<input type="hidden" id="pclist_ownerID" name="pclist_ownerID" />' +
                    '<table id="' + gridID + '"></table>' +
                    '<div id="' + pagerID + '"></div>' +
                   '</div>');
    var owner = $('#pclist_ownerID', markup);
    markup.dialog({
        autoOpen: false, modal: true, stack: true, resizable: false, position: 'center',
        width: 860, height: 400,
        close: function (event, ui) {
            $(gridID).jqGrid('GridUnload');
            $(this).dialog('destroy');
            $(this).remove();
        }
    });

    $.ajax({
        url: 'MyWebService.asmx/GetAdditionalData',
        type: "post",
        dataType: "json",
        async: false,
        data: JSON.stringify({ objectID: objectID }),
        contentType: "application/json; charset=utf-8",
        success: function (data) {
            var title = titlePrefix + data.d.objectname + " - " + data.d.period;
            markup.dialog("option", "title", title);
            owner.val(data.d.workgroupid);
        }
    });
    markup.dialog('open');
    var grid = $('#' + gridID);
    grid.jqGrid({
        url: 'MyWebService.asmx/MyMethod',
        colNames: [
            'Field1',
            'Field2',
            'Field3'
        ],
        colModel: [
            { name: 'Field1', index: 'Field1', width: 120, sortable: false, align: 'left', search: true, template: colTextTemplate, searchrules: { required: false } },
            { name: 'Field2', index: 'Field2', width: 170, sortable: false, align: 'left', search: true, template: colTextTemplate, searchrules: { required: false} },
            { name: 'Field3', index: 'Field3', width: 170, sortable: false, align: 'left', search: true, template: colTextTemplate, searchrules: { required: false} }
        ],
        serializeGridData: function (postData) {
            if (postData.filters === undefined) postData.filters = null;
            return JSON.stringify(postData);
        },
        jsonReader: {
            id: "MyRecordID"
        },
        footerrow: false,
        userDataOnFooter: true,
        sortname: 'MyRecordID',
        sortorder: "asc",
        pager: $('#' + pagerID),
        rownumbers: true,
        gridComplete: function () {
            //this method just enable or disable the add/edit/delete based on conditions 
            reconfigPermissions();
        },
        gridview: true,
        autowidth: false,
        shrinkToFit: false,
        width: 830,
        height: 264
    })
    .jqGrid('navGrid', '#' + pagerID,
        {
            add: true, addtitle: 'Add Record',
            edit: true, edittitle: 'Edit Record',
            del: true, deltitle: 'Delete Record',
            refresh: false,
            search: false,  //searchtitle: 'Advanced search filters',
            addfunc: function () {
                // code for add
            },
            editfunc: function () {
               // code for edit
            }
        },
        { /*default settings for edit*/ },
        { /*default settings for add*/ },
        {
            /* settings for delete*/
            // define settings for Delete 
            mtype: "post", reloadAfterSubmit: true,
            url: 'MyWebService.asmx/Delete',
            resize: false,
            serializeDelData: function (postdata) {
                return JSON.stringify({ recordID: postdata.id });
            },
            afterSubmit: function (data, postdata) {
            }
        },
        {},
        {}
    )
    .jqGrid('navSeparatorAdd', '#' + pagerID, {})
    .jqGrid('navButtonAdd', '#' + pagerID, {
        caption: "", buttonicon: "ui-icon-search", position: "last", title: "Advanced search filters",
        onClickButton: function () {
            grid.searchGrid({
                sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge', 'bw', 'cn'],
                closeOnEscape: true, multipleSearch: true, closeAfterSearch: true, recreateFilter: true
            });
        }
    });
}

非常感谢您的帮助!

编辑:对此没有任何建议?

【问题讨论】:

    标签: jquery jquery-ui memory-leaks jqgrid jquery-ui-dialog


    【解决方案1】:

    一切听起来都很奇怪。 jqGrid 工作不干净的内存。尽管如此,我不认为每次打开对话框后增加 30 MB 的内存只能由 jqGrid 来解释。您使用的网格不包含rowNum。因此将使用默认值 20(请参阅the documentation)。您不使用 loadonce: true 选项,因此在网格中用作 URL 的 'MyWebService.asmx/MyMethod' 应该返回大约 20*4 的单元格值(3 列 + id 列)。这样的响应和 jqGrid 创建的所有 DOM 结构不能占用 30 MB 内存。

    所以我想问题的原因可能是 jqGrid 的其他原因。您可以使用 Fiddler、IE 或 Chrome 的开发者工具来跟踪 HTTP 流量。我建议您验证来自'MyWebService.asmx/MyMethod''MyWebService.asmx/GetAdditionalData' 的回复。可能是某些响应包含太多数据。减少数据并不能真正解决问题,但 30 KB 的内存泄漏不会像 30 MB 大小的泄漏那么重要。顺便说一句,您可以使用userData 并在loadComplete 内刷新对话框的标题(制作同一组对话框选项“标题”)。这样您就可以保存同步 (async: false ???) Ajax 调用。

    此外,我建议您将datatype 选项从"json" 更改(临时,仅用于测试)到"local"。在这种情况下,不会对 URL 'MyWebService.asmx/MyMethod' 进行请求,您可以验证方法调用和填充网格数据是否负责 30 MB,这是您的主要问题。

    你会建议你另外使用 jqGrid 的deepempty: true 选项。

    如果您的所有测试都表明 jqGrid 确实对内存泄漏负责,那么您将不得不替换 $(gridID).jqGrid('GridUnload'); 调用以递归清理 jqGrid 创建的所有 DOM 结构(单元格和行)。我希望它不会被需要。

    【讨论】:

    • 好吧,为简单起见,我没有报告所有列。实际上网格有 11 列 + ID 列。其中 10 列是字符串数据,最后一列是浮点值。最多返回 15 条记录。但是我认为代码不仅在 jqGrid 上泄漏,而且在对话框创建部分也泄漏。您能否建议$(gridID).jqGrid('GridUnload'); 的替代方案?
    • 感谢您提及deepempty 参数!
    • @Lorenzo:我建议您首先尝试使用datatype: "local" 来验证 30 MB 内存泄漏是否真的来自 jqGrid。人们可以投入大量时间寻找根本没有问题的问题。所以首先应该验证 jqGrid 是 30 MB 内存泄漏的根源。
    • @Lorenzo:你找到30 MB内存泄漏问题的原因了吗?原因是什么?
    • 如你所料,这并不是 jqGrid 的错。但是 deepemty 参数的使用效果很好。此外,我通过将对话框的代码添加到页面标记中而不是将其留在内存中,对对话框的代码进行了一些更改。
    猜你喜欢
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    相关资源
    最近更新 更多