【问题标题】:Speeding up Datatables load time on client side加快客户端的数据表加载时间
【发布时间】:2014-03-03 07:53:20
【问题描述】:

我在客户端使用 datatablejs 向客户端显示数据库。我最初使用主干 indexeddb 适配器从服务器下载数据库并将其存储在 indexedDB 中,以支持对数据的离线访问。但是,数据表大约需要 5 分钟来呈现 20,000 个条目。这是我的 JS 代码:

render_data: function(entity_collection) {
        //create table body in memory
        tbody = $('<tbody>');
        tbody.html('');

        //iterate over the collection, fill row template with each object 
        //and append the row to table
        entity_collection.each(function(model) {
            tbody.append(this.row_template(model.toJSON()));
        }, this);
        //put table body in DOM
        this.$('#list_table')
            .append(tbody);
        //initialize datatable lib on the table    
        this.$('#list_table')
            .dataTable();
        $("#loaderimg")
            .hide();
        $("#sort-helptext").show();
},

表头:

<script type="text/template" id="person_table_template"> 
    <tr> 
        <th>Id</th> 
        <th>Name</th> 
        <th>Father Name</th> 
        <th>Village</th> 
        <th>Group</th> 
        <th></th> 
    </tr> 
</script>

转成html的JSON:

Object {
    age: 45, 
    father_name: "Jiyan Sah ", 
    gender: "F", 
    group: Object, 
    id: 10000000155392, 
    label: "Gangajali Devi (Sahila Rampur,Jiyan Sah )", 
    online_id: 10000000155392, 
    person_name: "Gangajali Devi ", 
    phone_no: "", 
    resource_uri: "/coco/api/v1/person/10000000155392/", 
    village: Object
}

谁能建议如何提高数据表的性能?

【问题讨论】:

  • 能否提供示例数据行和模板?
  • @DamianKrawczyk 表头:
  • 转换为html的JSON:对象{年龄:45,父亲姓名:“Jiyan Sah”,性别:“F”,组:对象,id:10000000155392,标签:“Gangajali Devi (Sahila Rampur ,Jiyan Sah )", online_id: 10000000155392, person_name: "Gangajali Devi", phone_no: "", resource_uri: "/coco/api/v1/person/10000000155392/", videos_seen: Array[19], Village: Object}
  • 我的 2cents,我们为什么不假设延迟也部分在浏览器上,将表格绘制到页面上。为其添加一个 table-layout:fixed 样式,看看是否有帮助。更多信息在这里w3.org/TR/CSS2/tables.html#propdef-table-layout

标签: javascript jquery-datatables


【解决方案1】:

尝试直接从您的 js 对象构建数据表(请参阅DataTables Example here),而不是先构建 DOM 对象。

也许 datatablejs 在评估 json 数组时比分析如此大的 DOM 对象(并再次删除大部分对象)更快

这样你可以设置"bDeferRender": true,这将导致datatablejs只会渲染可见的行,给你一个巨大的速度提升(见the datatablejs features page

通过使用 js 数组初始化,您当然会失去没有 JavaScript 的用户的 HTML 回退 - 但我想这不是您的受众;-)

也看看disabling CSS height matching 这可以为您节省一些渲染时间。

【讨论】:

  • “也许 datatablejs 在评估 json 数组时比在分析如此大的 DOM 对象时更快”我会尝试这个,但我也不确定它是否会起作用。
【解决方案2】:

如果您想提高速度,请使用 Javascript 编写自己的函数,而不是使用 Jquery。

!!!!首先追加然后添加更快。 !!!!!!

也使用 cloneNode,它比 document.createElement 更快,只创建一次并克隆。 看看这个并放在html

生成一个包含 20000 个条目的数据表需要 700 毫秒,当然这取决于机器和数据读取

 var a=new Date().getTime ();
 var table_master=document.createElement ("table");
 var tbody_master=document.createElement ("tbody");
 var tr_master=document.createElement ("tr");
 var td_master=document.createElement ("td");
 var i,u, tr, td;
 document.body.appendChild (table_master);
 table_master.appendChild (tbody_master);

 for (i=0;i<4000;i++)
        {
        tr=tr_master.cloneNode ();
        tbody_master.appendChild(tr);   // check what happens if you put this line after for operation , when you first add the cells with data to tr and then append to the tbody, that would slow down imense
        for (u=0;u<5;u++)
            {
            td=td_master.cloneNode();
            tr.appendChild (td);
            td.appendChild (document.createTextNode("hello"));
            }
        }

【讨论】:

  • 这肯定会有所帮助。但是数据表提供了搜索和排序功能。如果我们使用这个解决方案,我们将不会得到它。
  • 但是至少你可以按照我告诉你的那样设置你的dom,试试看,先追加然后添加,你正在做对手.....你把单元格放在行中到 tbody , tbody 到表,然后 tbody 到 DOM,以另一种方式尝试,首先将表附加到 Dom,然后将 tbody 附加到表,然后附加行,然后附加单元格,然后附加数据
  • this.$('#list_table').dataTable();语句占用了 99% 的加载时间。这句话对我来说是个问题。就我而言,附加到 DOM 所花费的时间可以忽略不计。
【解决方案3】:

嘿,兄弟,看看这个,这可能对你有帮助-------

客户端代码-----

$("#table-tripNote").dataTable({
                "oLanguage": {
                    "sZeroRecords": "No records to display",
                    "sSearch": "Search from all Records"
                },
                "bProcessing": true,
                "bServerSide": true,
                "bDestroy": true,
                "sAjaxSource": "frmTrip.aspx/GetMemberNotesByTrip",
                "sPaginationType": "full_numbers",
                "bDeferRender": true,
                "aoColumns":
                            [
                                null,
                                null,
                                null,
                                null,
                                null,
                                null,
                                null
                            ],
                "fnServerData": function (sSource, aoData, fnCallback) {
                    $.ajax({
                        "dataType": 'json',
                        "contentType": "application/json; charset=utf-8",
                        "type": "GET",
                        "url": sSource,
                        "data": aoData,
                        "success":
                                                    function (msg) {

                                                        var json = jQuery.parseJSON(msg.d);
                                                        fnCallback(json);
                                                        $("#table-tripNote").show();
                                                    }
                    });
                }
            });

服务器端代码---

[WebMethod()]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public static string GetMemberNotesByTrip(string sEcho, int iDisplayStart, int iDisplayLength)
{

    string rawSearch = HttpContext.Current.Request.Params["sSearch"].Trim();

    var whereClause = string.Empty;

    var filteredWhere = "1=1";

    var wrappedSearch = rawSearch.Trim();
    var Tempsb = new StringBuilder();

    Tempsb.Append("mbrid=" + MemberID);
    if (TripID != 0)
    {
        Tempsb.Append("and trpid=" + TripID);
    }
    else
        Tempsb.Append("and trpid=0");

    if (rawSearch.Length > 0)
    {
        Tempsb.Append("AND ( ISNULL(trpDate,'''') LIKE ");
        Tempsb.Append("'%" + wrappedSearch + "%'");
        Tempsb.Append(" OR clrFullName LIKE ");
        Tempsb.Append("'%" + wrappedSearch + "%'");
        Tempsb.Append(" OR clrPhone LIKE ");
        Tempsb.Append("'%" + wrappedSearch + "%'");
        Tempsb.Append(" OR clrRelationshipToMember LIKE ");
        Tempsb.Append("'%" + wrappedSearch + "%'");
        Tempsb.Append(" OR trpNote LIKE ");
        Tempsb.Append("'%" + wrappedSearch + "%'");
        Tempsb.Append(" OR clrOrganization LIKE ");
        Tempsb.Append("'%" + wrappedSearch + "%'");
        Tempsb.Append(" OR trpIsGrievance LIKE ");
        Tempsb.Append("'%" + wrappedSearch + "%'");
        Tempsb.Append(")");
    }

    if (Tempsb.Length > 0)
        filteredWhere = Tempsb.ToString();

    string orderByClause = string.Empty;
    orderByClause = "trpDate desc";

    StringBuilder sb = new StringBuilder();
    sb.Append(Convert.ToInt32(HttpContext.Current.Request.Params["iSortCol_0"]));

    sb.Append(" ");

    sb.Append(HttpContext.Current.Request.Params["sSortDir_0"]);

    orderByClause = sb.ToString();

    if (!String.IsNullOrEmpty(orderByClause))
    {
        orderByClause = orderByClause.Replace("0", ", trpDate ");
        orderByClause = orderByClause.Replace("1", ", clrFullName ");
        orderByClause = orderByClause.Replace("2", ", clrPhone ");
        orderByClause = orderByClause.Replace("3", ", clrRelationshipToMember ");
        orderByClause = orderByClause.Replace("4", ", clrOrganization ");
        orderByClause = orderByClause.Replace("5", ", trpIsGrievance ");
        orderByClause = orderByClause.Replace("6", ", trpNote ");

        orderByClause = orderByClause.Remove(0, 1);
    }
    else
    {
        orderByClause = "pronID ASC";
    }

    DataSet ds = clsTrip.GetTripNotesMaster(filteredWhere, orderByClause, iDisplayLength, iDisplayStart, true);


    List<clsTrip> lstTripNotesGrv = new List<clsTrip>();
    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
    {
        clsTrip lsttripNotes = new clsTrip();
        lsttripNotes.clrFullName = ds.Tables[0].Rows[i]["clrFullName"].ToString();

        if (!string.IsNullOrEmpty(ds.Tables[0].Rows[i]["trpDate"].ToString()))
            lsttripNotes.trpDate = Convert.ToDateTime(ds.Tables[0].Rows[i]["trpDate"].ToString());
        else
            lsttripNotes.trpDate = DateTime.MinValue;

        lsttripNotes.clrPhone = ds.Tables[0].Rows[i]["clrPhone"].ToString();
        lsttripNotes.clrRelationshipToMember = ds.Tables[0].Rows[i]["clrRelationshipToMember"].ToString();
        lsttripNotes.clrOrganization = ds.Tables[0].Rows[i]["clrOrganization"].ToString();

        if (!string.IsNullOrEmpty(ds.Tables[0].Rows[i]["trpIsGrievance"].ToString()))
            lsttripNotes.trpIsGrievance = Convert.ToBoolean(ds.Tables[0].Rows[i]["trpIsGrievance"].ToString());
        else
            lsttripNotes.trpIsGrievance = false;
        lsttripNotes.trpNote = (ds.Tables[0].Rows[i]["trpNote"].ToString());

        lstTripNotesGrv.Add(lsttripNotes);
    }
    int TotalRec = Convert.ToInt32(ds.Tables[1].Rows[0][0]);

    var result = from c in lstTripNotesGrv
                 select new[] { 
                       //Convert.ToString(c.pronID),                               
                       c.trpDate !=null && c.trpDate!=DateTime.MinValue ? string.Format("{0:MMM d, yyyy}",c.trpDate):"-",
                       c.clrFullName.ToString(),
                       c.clrPhone.ToString(),
                       c.clrRelationshipToMember.ToString(),
                       c.clrOrganization.ToString(),
                       ( Convert.ToBoolean(c.trpIsGrievance)?"Yes":"No"),
                       c.trpNote
                   };

    JavaScriptSerializer jss = new JavaScriptSerializer();
    return jss.Serialize(new
    {
        sEcho,
        iTotalRecords = TotalRec,
        iTotalDisplayRecords = TotalRec,
        aaData = result
    });
}

【讨论】:

  • 从 indexedDB 中检索数据有什么帮助?我所有的数据都保存在 IndexedDB 中。
【解决方案4】:

首先,每次迭代都不需要追加数据,循环后一次即可。

var tmp_str = '';

entity_collection.each(function(model) {
    tmp_str+=this.row_template(model.toJSON())
}, this);

tbody.append(tmp_str);

但要真正加快应用程序的速度,我建议您更改渲染方式 - 现在您一次渲染所有数据并且不知道观看了哪一部分信息,但客户端。延迟加载可以帮助您 - 例如。您渲染前 100 个项目,当页面滚动到您渲染 + 100 的列表的底部时,依此类推。

如果您需要一些代码帮助,请告诉我。

【讨论】:

  • 我同意延迟加载是一种解决方案,但唯一的问题是我的数据在索引数据库中,所以我不需要发送 ajax 调用。而 DOM 也无济于事。
  • 这样您就可以从 indexeddb 和渲染切片构建一个集合,或者通过有限的查询获得必要的切片
  • 我们如何从 indexeddb 构建集合?
  • @Gaurav 检查这些东西 - html5rocks.com/en/tutorials/indexeddb/todo - 它是关于如何使用 indexeddb 的。在 Backbone 端遵循此逻辑 - 创建 BB 集合的实例,将其传递给视图并在集合重置事件时订阅此视图。最后,当您从 indexeddb 查询中获取数据并将其处理为适当的结构(需要)时,使用 .reset 方法将此数据传递给 BB 集合。
  • 你测试了吗?正如你所说的那样一次添加所有内容至少比添加每个尝试都慢。原因是 CSS 变慢了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-11
  • 1970-01-01
  • 2021-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多