Как оптимизировать добавление многочисленных элементов динамически на веб-страницу - PullRequest
6 голосов
/ 03 июня 2019

Мне нужно извлечь много записей из моей базы данных и показать их пользователям.Я делаю это с помощью ajax и сохраняю все, что нужно добавить на страницу в одну строку.В настоящее время у меня проблема со временем загрузки (1 секунда на каждые 100 записей).например, для загрузки 1000 строк требуется 10 секунд, а сам запрос может быть полностью выполнен менее чем за 1 секунду.Это означает, что узким местом является создание элементов и добавление их на веб-страницу.

//client side code    
$(document).ready(function () {
    loadGrid(function () {
    $(".rowCount").val($(".tbody .tr:visible").length);
});

function loadGrid(callback) {
    $.ajax({
        type: "POST", url: "Ledger.aspx/LoadGrid",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            $(".tbody").html(response.d);   //response.d = '<div class='tr'> <div class='td colIdVchItm'>1</div>...</div>'
            callback();
        },
        failure: function (response) {
            ShowMessage(response.d);
        }
    });
}

//server side code
[WebMethod]
    public static string LoadGrid()
    {
        string q = @"select cast((select 'tr' as [@class],  
'td colIdVchItm' as [div/@class] , a.IdVchItm as [div], ' ',
'td colNo' as [div/@class] , a.No as [div], ' ',
'td colRef' as [div/@class] ,a.Ref as [div], ' ',
'td colSeq' as [div/@class] ,a.Seq as [div], ' ',
'td colDescr' as [div/@class] ,a.Descr as [div], ' ',
'td colDebit' as [div/@class] , cast(a.Debit as decimal(38,0)) as [div], ' ',
'td colCredit' as [div/@class] , cast(a.Credit as decimal(38,0)) as [div], ' ',
'td colBalance' as [div/@class] ,null as [div] , ' ',
'td colCur' as [div/@class] ,b.Title as [div], ' ',
'td colCurVal' as [div/@class] ,a.CurVal as [div], ' ',
'td colEffDate' as [div/@class] ,dbo.ShamsiDate(a.EffectiveDate) as [div] , ' '
from a inner join Currency as b on a.IdCur = b.IdCur order by a.vchdate, a.no
for xml path('div')) as nvarchar(max))";
        // this query returns every records as an html text. for example: 
        // <div class='tr'> <div class='td colIdVchItm'>1</div>...
        string res = "";
        SqlConnection con = new SqlConnection(DAL.conStr);
        SqlCommand com = new SqlCommand(q, con);
        con.Open();
        SqlDataReader rd = com.ExecuteReader();
        rd.Read();
        res = rd[0].ToString();
        con.Close();
        return res;
    }

Буду признателен, если вы поможете мне оптимизировать этот процесс.

Ответы [ 4 ]

2 голосов
/ 10 июня 2019

@ Bhenam: $ (". Tbody"). Html () внутренне использует innerHTML, который требует перестроения DOM, но с методом jquery append (), который добавляет содержимое в конец потомков в этом узле.

Можете ли вы попробовать с приведенным ниже кодом.

 success: function (response) {
            $(".tbody").html('');
             $(".tbody").append(response.d);

            callback();
        }

Поддерживается всеми браузерами. https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild

0 голосов
/ 13 июня 2019

Попробуйте, используйте функцию append () вместо html (), как упоминалось Madhusudana, если вы используете html (), то де-факто ваш ajax-вызов перерисовывает всю страницу для каждого вызова:

//client side code    
    $(document).ready(function () {
        loadGrid(function () {
        $(".rowCount").val($(".tbody .tr:visible").length);
    });

function loadGrid(callback) {
    $.ajax({
        type: "POST", url: "Ledger.aspx/LoadGrid",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            $(".tbody").append(response.d);   //response.d = '<div class='tr'> <div class='td colIdVchItm'>1</div>...</div>'
            callback();
        },
        failure: function (response) {
            ShowMessage(response.d);
        }
    });
}
0 голосов
/ 11 июня 2019

вы получаете все данные записи в одном запросе. вместо быстрой загрузки вы можете попробовать ленивую загрузку.

сразу 200 записей, проходящих через ajax. Пожалуйста, примените ограничение на стороне сервера.

    var offset = 200,page=0; 
   //client side code    
    $(document).ready(function () {
        loadGrid(function () {
        $(".rowCount").val($(".tbody .tr:visible").length);
    });

    function loadGrid(callback) {
        $.ajax({
            type: "POST", url: "Ledger.aspx/LoadGrid",
            data: {offset:offset,start:page},
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (response) {
               if(response){

                $(".tbody").append(response.d);   //response.d = '<div class='tr'> <div class='td colIdVchItm'>1</div>...</div>'
                callback();
                 if($(".tbody .tr:visible").length % offset == 0){
                     page++;
                     loadGrid(callback);
                 } 
                }
            },
            failure: function (response) {
                ShowMessage(response.d);
            }
        });
    }
0 голосов
/ 10 июня 2019

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

Один из самыхПри работе с огромным количеством данных важно всегда использовать подкачку страниц (загружать х количество данных на страницу).Даже если выполнение вашего запроса занимает 1-2 секунды, время для огромного количества данных для достижения пользовательского интерфейса увеличивается в зависимости от сетевого подключения на стороне клиента.

Другое дело, если вы просто отправляете данные из бэкэнда и строите строку html на внешнем интерфейсе, вы сэкономите много времени на загрузку этих данных, так как их значительно меньше.

Другие быстрые советы по устранению некоторых проблем во внешнем интерфейсе:

  • Максимально ограничьте доступ к DOM.Вы обращаетесь к DOM дважды, один раз, чтобы добавить html в tbody, второй, когда вы вычисляете длину видимых строк, которую вы можете предотвратить, отправляя только данные из бэкенда и вычисляя длину и создавая строки html во внешнем интерфейсе.И вы можете передать это в функцию обратного вызова сетки загрузки.
  • Попробуйте использовать ID, если это возможно.Когда вы используете класс в качестве селектора, он должен пройти через весь DOM и проверить наличие нескольких случаев этого конкретного случая.И, скорее всего, вы добавляете строки в одном месте.Используйте идентификатор, чтобы он не проходил через остальную часть документа.
  • Попробуйте вернуть false;после каждой функции.Во многих местах это не имеет большого значения, но если у вас огромный файл javascript, это немного повышает производительность.

function() { //DOM manipulation code here ..... return false;

Javascript ведет себя так: если он не видит возврата функций, он переходит в начало страницы и пересчитывает, какую функцию или инструкцию выполнить следующим,Если у вас есть возврат, он автоматически переходит к следующему шагу.

Надеюсь, это поможет.Если это не дает более подробной информации и показывает скриншоты производительности и журналы сети, если это возможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...