循环期间jQuery非常慢,我可以改进什么?

时间:2016-12-22 16:02:40

标签: javascript jquery performance loops

我有一些代码从数据库加载大约5,000行数据。一旦AJAX调用获取行,它就会将它们传递给我的函数来创建行。这个函数遍历JSON数据,创建我们的TR,进行一些查找,然后最终将完整的连接输出附加到DOM。

在文档加载时,我获取1,000条记录并将其附加到用户的DOM中,以便他们可以看到一些数据。然后我在幕后进行AJAX调用以获取其余部分,并在完成后附加它。浏览器在此期间锁定,但是在循环数据时。

在我的测试期间,我评论了each loop并且问题消失了,所以我把它缩小到了那个范围。我只是不确定如何改进它或者getObjects的查找功能是否会延迟它。

在下面的代码示例中,缓慢从$(data['data']['results']['data']).each(function() {开始,至少,这是我注释掉的代码块并且运行顺利。

如果没有让问题过于开放以解决问题,我可以从$.each循环中除了可以改善这一点的其他选项,还是循环内发生的可能导致缓慢的事情?

// Given data, create our table rows
function createRows(data) {

    // Define our vars
    var output = '',
        markup = '';

    // Add the fields we chose to export to the array
    // We will then check this array when printing the columns to see if it should be shown or not
    if (isset(data.data.exportFields)) {
        $(data.data.exportFields.export).each(function() {
            exportFields.push(this.fieldID);
        });
    }

    // Loop over the core data
    $(data['data']['results']['data']).each(function() {

        // First level of data in our XML output
        core = $(this)[0];

        // Loop over our fields
        $(core['fields']['data']).each(function() {

            // Set a var for the field level data
            field = $(this)[0];

            // Do we have markup?
            if (isset(data.data.markup)) {
                markup = '';
                if (typeof getObjects(data.data.markup.data, 'QID', core.QID)[0] !== 'undefined') {
                    markup = getObjects(data.data.markup.data, 'QID', core.QID)[0].markup;
                }
            }

            output += '<tr class="primaryValue ' + markup + '" data-qid="' + core.QID + '">';

            // Loop over all the other rows 2 through x
            $.each(field, function(key, value) {

                // Field Name Lookup
                key = key.replace(/_/gi, '');
                FieldNameLookup = getObjects(cfgFields.data.fields.options, 'FieldID', key)[0];
                x = FieldNameLookup.FieldName;
                val = (value.length ? value : '-')

                // Is this an email address?
                if (x.match(/email/gi)) {
                    output += '<td data-tableexport-display="always" class="small ' + (jQuery.inArray(key, exportFields) != -1 ? 'hidden' : '') + '">';
                    output += '<a href="mailto:' + val + '" class="">' + val + '</a>';
                    output += '</td>';
                } else if (x.match(/NTID/gi)) {
                    output += '<td data-tableexport-display="always" class="small ' + (jQuery.inArray(key, exportFields) != -1 ? 'hidden' : '') + '">';
                    output += '<a href="https://website.com/profile/' + val + '" target="_BLANK" class="">' + val + '</a>';
                    output += '</td>';
                } else {
                    output += '<td data-tableexport-display="always" class="small ' + (jQuery.inArray(key, exportFields) != -1 ? 'hidden' : '') + ' allowContext">';
                    output += val;
                    output += '</td>';
                }

            });

            // End our row
            output += '<td data-tableexport-display="always" class="notesTD allowContext hidden"></td>';
            output += '</tr>'

        });
    });

    // Append the results to the DOM
    $('[name=resultsTable]').append(output);

}

function getObjects(obj, key, val) {
    var objects = [];
    for (var i in obj) {
        if (!obj.hasOwnProperty(i)) continue;
        if (typeof obj[i] == 'object') {
            objects = objects.concat(getObjects(obj[i], key, val));
        } else if (i == key && obj[key] == val) {
            objects.push(obj);
        }
    }
    return objects;
}

3 个答案:

答案 0 :(得分:1)

这里有几件事。你有三层嵌套循环。循环越多,嵌套循环越多。将循环分解为自己的函数可能是最有效的,因为它们有自己的目的。以这种方式修改和推理它们会更容易。主要原因是,即使您可能带回1,000条记录,内部循环也必须根据它们所馈送的数组的长度来完成。

我认为另一个慢点是你创建DOM元素的方式。您可以使用纯JavaScript的jQuery创建它们,并将它们缓存在变量中,而不是在字符串中创建它们并将它们连接在一起。您可以在循环中填充其属性和内容。

Javascript BEST PRACTICES PART 2

Learn the slow (and fast) way to append elements to the DOM

enter link description here

答案 1 :(得分:0)

正如一些评论建议的那样,无限滚动在这里是个不错的选择。它减少了获取数据,处理数据然后显示数据的时间。 https://www.sitepoint.com/jquery-infinite-scrolling-demos/

我不知道您的数据是否可行,但我在移动应用程序中遇到了类似的问题,我只是将数据分成几类。然后我只根据类别加载数据。

答案 2 :(得分:0)

我建议将循环分解为更小的函数(甚至可能是递归函数),并将html作为节点传递,而不是作为文本传递(因此浏览器不需要重新渲染)。

像这样,但你必须填写一些空白:

function makeTd() {
  var hidden = exportFields.indexOf(key) > -1 ? "hidden" : "";
  var td = document.createElement('td');
  td.setAttribute('data-tableexport-display', 'always');
  td.className = "small";
  // conditionals for email, etc.
  return td;
}

function makeTr() {
  var tr = document.creatElement('tr');
  tr.className = "primaryValue";
  // logic ...
  return tr
}

$data.map(function(core, ci){

  core.map(function(field, fi) {
    var tr = makeTr();

    Object.key(field).map(function(output) {
      var key = output;
      var value = field[output];
      var td = makeTd(key, value);
      tr.appendChild(td);
    });

    var endTd = document.createElement('td');
    tr.appendChild(endTd);
  });
});