Javascript 使用DataTables时IE8长时间运行脚本错误

Javascript 使用DataTables时IE8长时间运行脚本错误,javascript,performance,Javascript,Performance,我有一个应用程序,它使用DataTables jQuery库在我的目标浏览器IE8中呈现内容。问题是,当我推动一个大数组进行渲染时,IE8有时会抛出臭名昭著的长时间运行脚本错误 分析应用程序后,以下代码中对_fnAddData的调用似乎是导致问题的原因: if (bUsePassedData) { for (var i = 0, len = oInit.aaData.length; i < len; i++) { _fnAddData(oSettings, oInit.aa

我有一个应用程序,它使用DataTables jQuery库在我的目标浏览器IE8中呈现内容。问题是,当我推动一个大数组进行渲染时,IE8有时会抛出臭名昭著的长时间运行脚本错误

分析应用程序后,以下代码中对_fnAddData的调用似乎是导致问题的原因:

if (bUsePassedData) {
  for (var i = 0, len = oInit.aaData.length; i < len; i++) {
      _fnAddData(oSettings, oInit.aaData[i]);
  }
} else if (oSettings.bDeferLoading ||
               (oSettings.sAjaxSource === null && oSettings.ajax === null)) {
  _fnAddTr(oSettings, $(oSettings.nTBody).children('tr'));
}

解决这个问题的好办法是什么?提前感谢。

我想您可以将您的功能分为3个功能:

function beforeIf(){
     if (bUsePassedData) {
       procesData(oSettings,oInit.aaData.concat());
     } else if (oSettings.bDeferLoading ||
                   (oSettings.sAjaxSource === null && oSettings.ajax === null)) {
       _fnAddTr(oSettings, $(oSettings.nTBody).children('tr'));
     }
     afterIF();
    }
function processData(oSettings,arr){
  //process in chuncks of 50;
  // setTimeout takes a long time in IE
  // it'll noticibly slow donw your script when
  // only processing one item at the time
  var tmp=arr.splice(0,50);
  for (var i = 0, len = tmp.length; i < len; i++) {
      _fnAddData(oSettings, tmp[i]);
  }
  if(arr.length!==0){
    setTimeout(function(){
      processData(oSettings,arr);
    },0);
    return;
  }
  afterIf();
}
function afterIf(){
  //continue processing
}
  • 在if语句之前
  • 处理oInit.aa数据
  • 在if语句之后
  • 下面是分为3个函数的代码:

    function beforeIf(){
         if (bUsePassedData) {
           procesData(oSettings,oInit.aaData.concat());
         } else if (oSettings.bDeferLoading ||
                       (oSettings.sAjaxSource === null && oSettings.ajax === null)) {
           _fnAddTr(oSettings, $(oSettings.nTBody).children('tr'));
         }
         afterIF();
        }
    function processData(oSettings,arr){
      //process in chuncks of 50;
      // setTimeout takes a long time in IE
      // it'll noticibly slow donw your script when
      // only processing one item at the time
      var tmp=arr.splice(0,50);
      for (var i = 0, len = tmp.length; i < len; i++) {
          _fnAddData(oSettings, tmp[i]);
      }
      if(arr.length!==0){
        setTimeout(function(){
          processData(oSettings,arr);
        },0);
        return;
      }
      afterIf();
    }
    function afterIf(){
      //continue processing
    }
    
    函数beforeIf(){
    if(总线组装数据){
    procesData(oSettings,oInit.aaData.concat());
    }else if(oSettings.bdeferload||
    (oSettings.sAjaxSource==null&&oSettings.ajax==null)){
    _fnAddTr(oSettings,$(oSettings.nTBody).children('tr');
    }
    afterIF();
    }
    函数processData(oSettings,arr){
    //工艺流程:50台;
    //在IE中设置超时需要很长时间
    //它会明显减慢你的脚本时
    //一次只处理一个项目
    var tmp=阵列拼接(0,50);
    对于(变量i=0,len=tmp.length;i
    谢谢@HMR。你帮助我更接近我的目标。为了解决这个问题,我把我的代码一直写到现在:

    (function processData(oSettings, arr) {
    
      var tmp = arr.splice(0, 50);
    
      tickApp.$orders.dataTable().fnAddData(tmp);
    
      if (arr.length !== 0) {
        setTimeout(function () {
          processData(oSettings, arr);
        }, 0);
      }
    }(oSettings, oInit.aaData.concat()));
    
    我没有使用private _fnAddData函数,而是选择了DataTables public fnAddData()函数。通过这种方式,我可以一次将50行推入存储在tickApp中的表中。$orders对象,我只是对存储在内存中的jQuery对象的引用:

    tickApp.$orders = $('#orders');
    
    在我代码的另一部分。按照你的方式,它仍然是一次推一排,而不是整个50排


    再次感谢。

    如果您使用ajax获取数据,您可以覆盖datatables配置对象中的“fnServerData”。这将允许您获取要加载的数据,然后根据需要对其进行处理

    在我的例子中,我有一个通用的datatables配置对象,用于所有datatables。我用一个函数覆盖默认的fnServerData函数,该函数使用fnAddData和setTimeout将行以200行为一组传递到datatable,以再次调用该函数,直到所有数据都已处理完毕,最后我调用fnDraw来绘制该表

    var DEFAULT_CHUNK_SIZE = 200;
    
    function feedDataToDataTableInChunks(startIndex, data, oSettings) {
        var chunk = data.slice(startIndex, DEFAULT_CHUNK_SIZE);
        oSettings.oInstance.fnAddData(chunk, false);
        if((startIndex += DEFAULT_CHUNK_SIZE) < data.length) {
            setTimeout(function () {
                feedDataToDataTableInChunks(startIndex, data, oSettings);
            });
        } else {
            oSettings.oApi._fnInitComplete(oSettings, data);
            oSettings.oInstance.fnDraw();
        }
    }
    
    var config = {fnServerData: function(){
        oSettings.jqXHR = $.getJSON(sSource, aoData)
            .done(function (result) {
                feedDataToDataTableInChunks(0, result || [], oSettings);
            });
    }}
    
    var DEFAULT\u CHUNK\u SIZE=200;
    函数FeedDataToDataTableInChunk(起始索引、数据、oSettings){
    var chunk=data.slice(startIndex,默认块大小);
    oSettings.oInstance.fnAddData(chunk,false);
    if((startIndex+=默认块大小)

    我使用的是datatables 1.9.4版

    请注意,fnAddData方法有一个可选的第2个参数。此参数表示是否重新绘制表。默认值为true。因此,如果在没有第二个参数的情况下调用fnAddData 50次,它将重新绘制表50次。对于大表或大插入,这可能非常慢。谢谢@bumptiousqbangshilt!我想知道。。。由于我使用的数据表具有不同的行高,因此我没有明确设置css值,因此重新绘制该表不是很理想吗?它的运行速度非常快,但我会将其更改为更快。您在哪里定义传递给_fnInitComplete的json变量?抱歉,我在意识到忘记包含它后添加了对fnInitComplete的调用,我已更新了我的答案以正确使用它。