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

时间:2013-06-06 03:58:10

标签: javascript performance

我有一个应用程序,它使用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'));
}

我一直在寻找解决方案,并且看到Nicholas Zakas写了here以及其他许多解决方案,如果for循环不在if else if“block”中,那么这些解决方案将会起作用。当我尝试在第一次尝试许多时,将它包装在一个setTimeout函数中它当然不起作用,因为if else的第二部分如果解析为true。

(oSettings.sAjaxSource === null && oSettings.ajax === null) // true

这有什么好的解决方案?提前谢谢。

3 个答案:

答案 0 :(得分:0)

我认为你可能会将你的功能分成3个功能:

  1. 在if语句之前。
  2. 处理oInit.aaData
  3. 在if语句之后
  4. 以下是分为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
    }
    

答案 1 :(得分:0)

谢谢@HMR。你帮助我更接近目标。为了解决这个问题,我将代码编写到了IIFE:

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

我没有使用私有_fnAddData函数,而是选择了DataTables public fnAddData(http://datatables.net/ref#fnAddData)函数。通过这种方式,我可以一次将50行输入到存储在tickApp。$ orders对象中的表中,这只是对我将jQuery对象存储在内存中的jQuery对象的引用:

tickApp.$orders = $('#orders');

在我的代码的另一部分。你有这样的方式它仍然一次推动一排而不是整个50行。

再次感谢。

答案 2 :(得分:0)

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

就我而言,我有一个通用数据表配置对象,我用于所有数据表。我覆盖了默认的fnServerData函数,其中一个使用fnAddData和setTimeout将行传递给200个数据集,再次调用该函数直到所有数据都被处理完毕,最后我调用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);
        });
}}

我正在使用数据表版本1.9.4

相关问题