jQuery - менеджер, неполная загрузка диалога

230
08 октября 2018, 23:30

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

Сначала я получаю список сообщений на серверной части, а приёмник на стороне клиента через ajax запрос перехватывает и из этих данных делает переменную типа string, которую потом я использую как innerHtml и вставляю его в лист сообщений.

PHP:

public function get_messages($id){
$chat = $this->db->find_one('users_chats', ['id' => $id]);
$messages = $this->db->find('users_messages', ['cid' => $id]);
if($chat != null){
    $user_ids = json_decode($chat['users_ids'], false);
    if(array_search($this->AM->user['id'], $user_ids) !== false) {
        if ($chat['type'] == 'private') {
            $chat['title'] = json_decode($chat['title'], true)[$this->AM->user['id']];
        }
        for ($i = 0; $i < count($messages); $i++) {
            $viewed = json_decode($messages[$i]['viewed'], false);
            if (array_search($this->AM->user['id'], $viewed) === false) {
                $viewed[] = $this->AM->user['id'];
                $views = json_encode($viewed);
                $this->db->update('users_messages', ['viewed' => $views], ['id' => $messages[$i]['id']]);
            }
            $messages[$i]['user'] = $this->db->find_one('users_accounts', ['id' => $messages[$i]['uid']], ['id', 'first_name', 'last_name', 'photo']);
        }
        echo json_encode(['type' => 'success', 'messages' => $messages, 'chat' => $chat]);
    }else{
        echo json_encode(['type' => 'error']);
    }
}else{
    echo json_encode(['type' => 'error']);
}
}

JS:

     function open_chat(id) {
    if($.cid != id || $.cid == null) {
        $.cid = id;
        $.ajax({
            url: '/get-messages/',
            method: 'POST',
            data: {cid: id},
            success: function (result) {
                result = JSON.parse(result);
                if (result['type'] == 'success') {
                    $('#content').children('.title').children('span').text(result['chat']['title']);
                    $('#content').show();
                    $('#no-content').hide();
                    var messages_list = result['messages'];
                    var messages_html_list = '';
                    [].forEach.call(messages_list, function (message) {
                        messages_html_list = messages_html_list +
                            '<div class="message"><div class="autor link_page" url="/u' + message['user']['id'] + '/records/"><div class="author-photo"><img src="' + message['user']['photo'] + '" alt=""></div>' +
                            '<div class="fullname">' + message['user']['first_name'] + ' ' + message['user']['last_name'] + '</div><div class="time" time="' + message['time'] + '"></div></div>' +
                            '<div class="text">' + message['message'] + '</div></div>';
                    });
                    $('#messages_list').html(messages_html_list);
                    $('#messages_list').scrollTop($('#messages_list').prop('scrollHeight'));
                    if (messages_list.length != 0) {
                        $.last_message_id = messages_list[messages_list.length - 1]['id'];
                    }
                    start_page();
                    set_checking();
                }
            }
        });
    }
}

Функцию openchat вызываю при клике на элемент "чата".

<div class="chat element" onclick="open_chat(<?=$chat['id']?>)">
        <div class="photo">
            <img src="<?=$chat['photo']?>" alt="">
        </div>
        <div class="main">
            <div class="name"><?=$chat['title']?></div>
            <div class="last-message">
            </div>
        </div>
    </div>

Но, по производительности это ужасно стучит. И, мне бы хотелось узнать, может вы сможете дать совет?

Answer 1

Немного переформатировал код для более быстрой работы js. но все же есть вопросы. о них ниже.

   function open_chat(id) {
     if ($.cid != id || $.cid == null) {
         $.cid = id;
         let $content = $('#content');
         let $no_content = $('#no-content');
         let $messages_list = $('#messages_list');
         let content_title = $content$content.children('.title').children('span');
         $.ajax({
             url: '/get-messages/',
             method: 'POST',
             data: { cid: id },
             success: function(result) {
                 result = JSON.parse(result);
                 if (result['type'] == 'success') {
                     $content_title.text(result['chat']['title']);
                     $content.show();
                     $no_content.hide();
                     var messages_list = result['messages'];
                     var messages_html_list = '';
                     [].forEach.call(messages_list, function(message) {
                         messages_html_list = `${messages_html_list} 
                        <div class="message"><div class="autor link_page" url="/u${message['user']['id']}/records/"><div class="author-photo"><img src="${$message['user']['photo']}" alt=""></div>
                        <div class="fullname">${message['user']['first_name']} ${message['user']['last_name']}</div><div class="time" time="${message['time']}"></div></div>                            '<div class="text">${message['message'] }</div></div>`;
                     });
                     $messages_list.html(messages_html_list);
                     $messages_list.scrollTop($messages_list.prop('scrollHeight'));
                     if (messages_list.length != 0) {
                         $.last_message_id = messages_list[messages_list.length - 1]['id'];
                     }
                     start_page();
                     set_checking();
                 }
             }
         });
     }
 }

Для поиска просадки я бы посоветовал использовать инструменты разработчика и посмотреть как быстро после вызова функции приходит ответ..если долго -смотрим сервер, если быстро (~100 мс или меньше) . то смотрим дальше js. по js быстро найти можно используя console.time('test');-- ставим в начале измерения, console.timeEnd('test'); -- соответственно в конце.и таким путем находим где конкретно просадка в js. Да, и формирование кода из строки намного медленнее чем если бы использовал создание элементов на чистом js. например let div = document.createElement('div'); let innerDiv = document.createElement('div'); innerDiv.textContent = 'text example'; div.append(innerDiv); document.boady.append(div); чем меньше перерисовок и изменений после вставки в dom, тем быстрее

READ ALSO
Не работает простой javascript в Chrome на Android 4.2 / 4.3

Не работает простой javascript в Chrome на Android 4.2 / 4.3

Есть форма (тест), содержащая несколько вопросов, на которые надо давать ответы путем выбора от 0 до 5 балловСделано радиокнопками:

168
Javascript событие для всех ссылок

Javascript событие для всех ссылок

Как заменить jquery код на javascript?

178
Нужна помощь по Redux

Нужна помощь по Redux

Вот есть допустим начальный state

158
Почему значение undefined?

Почему значение undefined?

После всех элементов в html файле располагаю скриптВ объекте page есть объект obj со значением $("

194