内存泄漏与jquery对话框e jqgrid

时间:2014-02-24 14:05:24

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

我有以下函数创建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
            });
        }
    });
}

非常感谢你的帮助!

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

1 个答案:

答案 0 :(得分: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内创建相同的对话框选项“title”)。在你保存同步(async: false ???)Ajax调用的方式。

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

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

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