Nano Hash - криптовалюты, майнинг, программирование

Таблицы данных ожидают массив, но получили объект (и ломаются, когда ожидают объект)

Сценарий

У нас есть таблица сотрудников, которая выглядит так:

введите здесь описание изображения

который содержит 16 530 строк сотрудников. Как и ожидалось, эта таблица загружается более 30 секунд. Мне поручили как-то его ускорить.

В качестве временной меры мы заблокировали этот пользовательский интерфейс экраном загрузки при загрузке страницы.

Что мы делали

  1. Получить всех сотрудников из API для магазина
  2. For each employee
    • convert it into an Employee object
    • получить его HTML-представление (через рендеринг шаблона)
    • поместите это HTML-представление в коллекцию
  3. инициализировать объект Datatables с этой коллекцией
  4. настроить столбцы Datatables и нарисовать таблицу

Что я сейчас делаю

  1. Получить всех сотрудников из API для магазина
  2. For each employee
    • convert it into an Employee object
    • поместите этот объект в коллекцию
  3. инициализировать объект Datatables с этой коллекцией
  4. adjust the Datatables columns and draw the table
    • On rowCallback, do the custom rendering logic

Реализация

На $(document).ready у нас есть следующая логика настройки таблицы:

var addbutton =
      '<button onclick="PopModel()" class="btn btn-success float-sm-left rounded"><i class="fa fa-user-plus" aria-hidden="true"></i> Add Employee</button>'
    var table_height = $('#with-content')
      .height() - 175
    var table = InitializeDatatable('#data-table', table_height, addbutton, 1, {
      paging: true,
      pageLength: 50,
      deferRender: true,
  /**
   * Invoked when a row is being created
   * @param {DomRow} row the row that datatables comes up with
   * @param {Object | Array} data the data we pass to datatables for the current row
   */
  createdRow: function(row, data) {
     data[0] = 'some image'
  },
  /**
   * Invoked after a row has been created
   * @param {DomRow} row the row that datatables comes up with
   * @param {Object | Array} data the data we pass to datatables for the current row
   */
  rowCallback: function(row, data) { 
    // render (or replace!) row here
    setTimeout(function() { 
      let employeeRowTR = new Employee()
        .ExtractFrom(data)
        .ToHTML()
      $(row).html(employeeRowTR.html())
    }, 4)
  }
})

let start = Date.now()
    GetEmployees(function (result, success) {
      if (success) {
        let tableRows  = []
        var ran = 0;
        for (let i = 0; i < result.length; i++) {
          const element = result[i];
          // progress bar logic
          setTimeout(function () {
            ran++;
            // adjust the progress bar state if it is defined
            if ($progressBar != null) {
              var percentValue = (ran / result.length) * 100
              $progressBar
                .css('width', percentValue + "%")
              if (percentValue == 100) {
                $('.dataTables_scrollBody')
                  .LoadingOverlay('hide')
              }
            }
            // extract an Employee object and add its HTML representation to datatables
            var employee = new Employee()
              .ExtractFrom(element)
            tableRows.push(employee)

            if (ran == result.length) { 
              table.rows.add(tableRows)
              table.columns.adjust()
                .draw();
            }
            if (ran == 50) {
              $('.dataTables_scrollBody')
                .LoadingOverlay("show", {
                  image: "",
                  custom: $progressBarDiv
                });
              $progressBar = $('#progressbar .progress-bar')
            }
          }, 1)
        }

        if (result.length == 0 && $('#task-selectpicker option')
          .length == 0) {
          Alert("It looks like there are no tasks created, would you like to create them before creating your employees?", "This can make things easier when setting up your employees.", function () {
            window.location = '/task/index'
          })
        }

      } else {
        var response = new ErrorResponse(result.responseText)
        response.Show()
      }
    })

Наш InitializeDatatable определяется как:

// Datatables
function InitializeDatatable(selector, table_height, addbutton, autoColumn = 0, customOptions = {}) {
  var randomButtonID = RandomID()
  var defaultOptions = {
    dom: `<"${randomButtonID}-addbutton">frtip`,
    scrollY: table_height,
    scrollCollapse: true,
    paging: true,
    info: false,
    order: [
      [autoColumn, 'asc']
    ],
    deferRender : true
  }
  $.extend(defaultOptions, customOptions)
  var table = $(selector)
    .DataTable(defaultOptions)

  $(`div.${randomButtonID}-addbutton`)
    .html(addbutton)
  return table
}

Обратите внимание, что как только сотрудники извлекаются из базы данных, мы конвертируем их в объекты Employee, которые имеют следующую логику представления HTML:

ToHTML() {
    // load in the employee template
    if (employeeTemplate == null) {
      employeeTemplate = FetchTemplate('employee/employee.html', "employee-template");
    }
    // render it with this
    var $element = employeeTemplate.tmpl(this);
    // get the picture and attach it directly to the view element that's being rendered
    this.GetPicture(function (picture) {
      $element.find('.person-image')
        .attr('src', picture.Picture)
        .data(picture);
    });
    // attach this model data to the view element and return it.
    return $element.data("model", this);
  }

Элемент таблицы (получен из серверной части)

<div id="with-content" class="table-full">
    <table id="data-table" class="table table-striped table-bordered" cellspacing="0" width="95%">
        <thead>
            <tr>
                <th scope="col"></th>
                <th scope="col">ID</th>
                <th scope="col">First Name</th>
                <th scope="col">Last Name</th>
                <th scope="col">Active</th>
                <th scope="col">Action</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
</div>

Проблема

Этот код, как он написан сейчас, ожидает, что каждый объект data будет массивом, поэтому он жалуется на загрузку страницы:

введите здесь описание изображения

При отклонении оповещения будут отображаться элементы строки таблицы, но когда вы нажмете на следующую страницу, оповещение появится снова. введите здесь описание изображения.

Указав некоторые columns следующим образом:

columns : [
    { data : "Id" },
    { data : "FirstName" },
    { data : "LastName" },
    { data : "IsActive" }
  ]

создает следующую проблему:

введите здесь описание изображения

Что я должен делать?

22.01.2019

  • Вам нужно разложить вашу проблему дальше, это слишком много, чтобы читать... 22.01.2019

Ответы:


1

Есть несколько проблем с вашим кодом.

  1. При использовании DataTable вы никогда не должны напрямую манипулировать DOM, как вы делаете с $(row).html(employeeRowTR.html()). Чтобы изменить внешний вид каждой ячейки, либо используйте columns.render() для каждого столбца, либо сгенерируйте HTML разметку для всей таблицы и только потом инициализировать плагин DataTables.

  2. Чтобы ускорить загрузку больших наборов данных, рассмотрите возможность использования обработки на стороне сервера.

23.01.2019
  • › используйте columns.render, подходит ли это также для асинхронных операций, таких как получение URL-адресов изображений из API? Я пытался сделать это в createdRow, но он не был готов, когда был вызван rowCallback. 24.01.2019
  • Я исправил проблему и, возможно, сегодня подробно расскажу о том, что я сделал. 28.01.2019
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..