1

我有一个应用程序,它使用 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 在这里写的以及大量其他解决方案,如果 for 循环不在 if else if “块”内,这些解决方案将起作用。当我第一次尝试将它包装在 setTimeout 函数中时,它当然不起作用,因为 if else if 的第二部分解析为 true。

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

对此有什么好的解决方案?提前致谢。

4

3 回答 3

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 对象的引用:

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

在我的代码的另一部分。他们按照你的方式,它仍然一次推 1 行,而不是整个 50 行。

再次感谢。

于 2013-06-06T07:59:16.943 回答
0

如果您使用 ajax 来获取数据,您可以在数据表配置对象中覆盖“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

于 2014-09-02T19:18:43.667 回答
0

我认为您可能会将您的功能拆分为 3 个功能:

  1. 在 if 语句之前。
  2. 处理 oInit.aaData
  3. 在 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
}
于 2013-06-06T04:30:15.157 回答